Как вы 'realloc' в C ++? - PullRequest
       2

Как вы 'realloc' в C ++?

75 голосов
/ 14 августа 2010

Как я могу realloc в C ++?Кажется, он отсутствует в языке - есть new и delete, но нет resize!

Мне это нужно, потому что, поскольку моя программа читает больше данных, мне нужно перераспределить буфер для его хранения,Я не думаю, что delete старый указатель и new новый, больший указатель - правильный выбор.

Ответы [ 4 ]

45 голосов
/ 14 августа 2010

Использование :: 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);

становится

t.resize(n2);

Если вы хотите передать указатель в функцию, вместо

Foo(t)

используйте

Foo(&t[0])

Это абсолютно правильный код C ++, потому что vector - это интеллектуальный массив C.

45 голосов
/ 14 августа 2010

Возможно, правильным вариантом будет использовать контейнер, который сделает всю работу за вас, например std::vector.

new и delete не могут изменить размер, поскольку они выделяют достаточно памяти для хранения объекта.данного типа.Размер данного типа никогда не изменится.Есть new[] и delete[], но вряд ли есть причина их использовать.

То, что realloc делает в C, вероятно, будет просто malloc, memcpy и freeв любом случае, хотя менеджерам памяти разрешено делать что-то умное, если имеется достаточно непрерывной свободной памяти.

33 голосов
/ 14 августа 2010

Изменение размера в 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[] для необработанных буферов, если только вы не реализуете векторный контейнер.

0 голосов
/ 17 января 2016

попробуйте что-то подобное:

typedef struct Board
{
    string name;
    int size = 0;
};

typedef struct tagRDATA
{
    vector <Board> myBoards(255);

    // Board DataBoard[255];
    int SelectedBoard;

} RUNDATA;

Вектор будет жаловаться. Вот почему массивы, malloc и new все еще существуют.

...