Является ли вектор STL лучшей версией realloc? - PullRequest
6 голосов
/ 15 апреля 2009

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

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

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

Спасибо

Ответы [ 5 ]

14 голосов
/ 15 апреля 2009

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

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

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

10 голосов
/ 15 апреля 2009

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

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

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

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

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

8 голосов
/ 15 апреля 2009

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

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

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

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

5 голосов
/ 15 апреля 2009

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

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

1 голос
/ 15 апреля 2009

Полагаю, это всего лишь вектор.

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

...