Как я могу realloc
на C ++? В языке вроде бы отсутствует - есть new
и delete
но нетresize
!
Мне это нужно, потому что по мере того, как моя программа читает больше данных, мне нужно перераспределить буфер для его хранения. Я не думаю, что delete
использовать старый указатель и new
использовать новый, более крупный - правильный вариант.
c++
new-operator
realloc
delete-operator
Bodacydo
источник
источник
Ответы:
Используйте :: std :: vector!
Type* t = (Type*)malloc(sizeof(Type)*n) memset(t, 0, sizeof(Type)*m)
становится
::std::vector<Type> t(n, 0);
потом
t = (Type*)realloc(t, sizeof(Type) * n2);
становится
Если вы хотите передать указатель в функцию вместо
использовать
Foo(&t[0])
Это абсолютно правильный код на C ++, потому что vector - это умный C-массив.
источник
Type* t = static_cast<Type*>(malloc(n * sizeof *t));
t.data()
вместо&t[0]
Правильный вариант, вероятно, использовать контейнер, который делает всю работу за вас, например
std::vector
.new
иdelete
не могут изменять размер, потому что они выделяют достаточно памяти для хранения объекта данного типа. Размер данного типа никогда не изменится. Естьnew[]
иdelete[]
но вряд ли когда - нибудь повод , чтобы использовать их.То, что
realloc
делает в C, вероятно, будет простоmalloc
,memcpy
иfree
, во всяком случае, хотя менеджерам памяти разрешено делать что-то умное, если имеется достаточно непрерывной свободной памяти.источник
std::vector
- он будет увеличиваться автоматически, когда это необходимо, и вы можете предварительно выделить память, если хотите (reserve()
).std::string
Кстати, так и может.)std::string
может это сделать. Кстати, есть шанс, что чтение данных тоже можно упростить. Как вы читаете свои данные?thevector.resize(previous_size + incoming_size)
, что за ним следуетmemcpy
(или что-то подобное)&thevector[previous_size]
, это то, что вам нужно. Данные вектора гарантированно хранятся «как массив».Изменение размера в C ++ неудобно из-за потенциальной необходимости вызывать конструкторы и деструкторы.
Я не думаю, что есть фундаментальная причина, по которой в C ++ у вас не могло быть
resize[]
оператора,new[]
и онdelete[]
делал что-то подобное:newbuf = new Type[newsize]; std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf); delete[] oldbuf; return newbuf;
Очевидно
oldsize
, будет получен из секретного места, в котором оно находитсяdelete[]
, иType
будет исходить из типа операнда.resize[]
потерпит неудачу, если тип не копируется - что правильно, поскольку такие объекты просто нельзя переместить. Наконец, приведенный выше код создает объекты по умолчанию перед их назначением, что вам не нужно в качестве фактического поведения.Возможна оптимизация
newsize <= oldsize
, при которой вызывать деструкторы для объектов «за концом» только что обработанного массива и больше ничего не делать. Стандарт должен определять, требуется ли эта оптимизация (как в случаеresize()
с вектором), разрешена, но не определена, разрешена, но зависит от реализации, или запрещена.Тогда вам следует задать себе следующий вопрос: «Действительно ли полезно предоставлять это, учитывая, что он
vector
тоже делает это, и разработан специально для предоставления изменяемого размера контейнера (непрерывной памяти - это требование опущено в C ++ 98, но исправлено в C ++ 03), что лучше, чем массивы с методами работы C ++? "Я думаю, что широко распространено мнение, что ответ - «нет». Если вы хотите сделать буферы с изменяемым размером в C, используйте те
malloc / free / realloc
, которые доступны в C ++. Если вы хотите изменять размер буферов, как в C ++, используйте вектор (илиdeque
, если вам действительно не нужно непрерывное хранилище). Не пытайтесь смешивать их, используяnew[]
для необработанных буферов, если только вы не реализуете векторный контейнер.источник
Вот пример std :: move, реализующий простой вектор с realloc (* 2 каждый раз, когда мы достигаем предела). Если есть способ добиться большего, чем копия, представленная ниже, пожалуйста, дайте мне знать.
Скомпилировать как:
g++ -std=c++2a -O2 -Wall -pedantic foo.cpp
Код:
#include <iostream> #include <algorithm> template<class T> class MyVector { private: T *data; size_t maxlen; size_t currlen; public: MyVector<T> () : data (nullptr), maxlen(0), currlen(0) { } MyVector<T> (int maxlen) : data (new T [maxlen]), maxlen(maxlen), currlen(0) { } MyVector<T> (const MyVector& o) { std::cout << "copy ctor called" << std::endl; data = new T [o.maxlen]; maxlen = o.maxlen; currlen = o.currlen; std::copy(o.data, o.data + o.maxlen, data); } MyVector<T> (const MyVector<T>&& o) { std::cout << "move ctor called" << std::endl; data = o.data; maxlen = o.maxlen; currlen = o.currlen; } void push_back (const T& i) { if (currlen >= maxlen) { maxlen *= 2; auto newdata = new T [maxlen]; std::copy(data, data + currlen, newdata); if (data) { delete[] data; } data = newdata; } data[currlen++] = i; } friend std::ostream& operator<<(std::ostream &os, const MyVector<T>& o) { auto s = o.data; auto e = o.data + o.currlen;; while (s < e) { os << "[" << *s << "]"; s++; } return os; } }; int main() { auto c = new MyVector<int>(1); c->push_back(10); c->push_back(11); }
источник
попробуйте что-нибудь вроде этого:
typedef struct Board { string name; int size = 0; }; typedef struct tagRDATA { vector <Board> myBoards(255); // Board DataBoard[255]; int SelectedBoard; } RUNDATA;
Вектор будет жаловаться. Вот почему все еще существуют массивы, malloc и new.
источник
typedef
везде, как если бы вы писали C.