Вопрос

Я считаю, что в C++ лучший способ справиться с перераспределением — использовать векторы STL, поскольку это гарантирует смежные места хранения.

У меня есть пара вопросов, чтобы понять разницу:

  1. Есть ли сценарий, в котором мне нужно предпочесть перераспределить над вектором?
  2. Есть ли что-нибудь еще (кроме вектора), что эквивалентно перераспределить на С++?

Спасибо,

Это было полезно?

Решение

Это только vector, который гарантированно имеет непрерывную память.Не другие.

realloc это функция управления памятью C.Его использование не поощряется в коде C++.Вот Страуструп, объясняющий почему: Почему в C++ нет эквивалента realloc()?

Однако функция realloc() гарантированно работает только с массивами, выделенными функцией malloc() (и аналогичными функциями), содержащими объекты без определяемых пользователем конструкторов копирования.Также помните, что вопреки наивным ожиданиям, функция realloc() иногда копирует свой массив аргументов.

Другие советы

Набор функций C (malloc, calloc, realloc, free) представляют собой необработанные операции с памятью.Они будут создавать/изменять/освобождать заданный буфер в памяти, но память не будет иметь типа и конструкторы не будут вызываться.

В C++ нет эквивалента перераспределить, но только типобезопасные эквиваленты malloc/free за счет использования новый/новый[] и удалить/удалить[].Обе версии C++ будут получать память из системы. и инициализируйте его, вызвав соответствующие конструкторы.С использованием удалить вызовет деструкторы объектов, а затем освободит память.Версии C и C++ несовместимы, если вы приобретаете память с помощью маллок (даже если вы вызываете конструктор inplace в полученной памяти), вы не можете освободить его с помощью удалить/удалить[] поскольку это неопределенное поведение.

С использованием перераспределить в C++ может быть небезопасно, поскольку он будет побитно копировать объекты из одной области памяти в другую.Иногда ваши объекты не могут должным образом обрабатывать перемещения в памяти (скажем, у вашего объекта есть и атрибут, и ссылка на него, после побитового перемещения ссылка будет указывать на старую позицию, а не на реальный атрибут).Внутри вектор, всякий раз, когда память должна увеличиться, новая память приобретается с новый[] а затем все объекты копируются (или копируются) в новые позиции с использованием соответствующих операций C++ перед удалением старых элементов.

В любое время вектор увеличивается в размере (зарезервированный размер, не используемый размер), он создаст совершенно новую область памяти и двигаться все объекты.С другой стороны, realloc переместит блок памяти в другую позицию только в том случае, если после указателя недостаточно непрерывного пространства, чтобы просто расти это. Векторы не уменьшайте размер.Никогда.Когда вы очищаете элементы, зарезервированная память все еще сохраняется.

Наконец, существует более высокий уровень абстракции в вектор чем в realloc, даже для типов POD (которые можно безопасно перемещать с помощью C-подобных конструкций).Эквивалент вектор будет структурой, которая содержит указатель на буфер памяти, количество используемых и зарезервированных элементов (размер буфера), а также набор функций, которые занимаются получением дополнительной памяти по мере необходимости и обновлением индексов при каждой операции.

Непрерывность памяти также гарантируется Realloc, так что это не повод не использовать ее.

Однако я бы предпочел использовать вектор в C++, поскольку он находится на более высоком уровне абстракции и, следовательно, упрощает написание кода.

Единственная возможная причина, по которой я могу использовать realloc (по вектору) для сценария типа массива, - это чистая скорость.Это может будь быстрее.И я подчеркиваю слово "может" - меряй, не угадывай!

Однако вам придется самостоятельно выполнять перераспределение, а это требует больше работы.Я бы предпочел иметь код, который работает немного медленнее (конечно, при условии, что он по-прежнему работает достаточно быстро), если я могу доставить его и получить оплату быстрее.

Одним из основных преимуществ std::vector является то, что когда он внутренне перераспределяет себя из естественного роста, он выбирает размер, который в 2 раза больше текущего размера (обычно - но всегда постоянный множитель).Это означает, что push_back имеет амортизированную стоимость O(1).

Realloc даст вам более точный контроль над распределением памяти, но с большими возможностями приходит и большая ответственность.Если все, что вы делаете, это эквивалент push_back, и вы перераспределяете память каждый раз, когда добавляете элемент, то есть потенциально операция O(N) при каждом добавлении в массив.

Я думаю, это всего лишь вектор.

Я не видел никого, кто бы предложил использовать realloc в C++.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top