Перераспределяет ли std :: vector :: reserve внутренний массив? - PullRequest
1 голос
/ 04 марта 2012

У меня есть функция, которая принимает int * и модифицирует передаваемый массив. Я заранее знаю, сколько элементов она получит. Допустим, это m значения.

Что произойдет, если я вызову reserve(m) для vector<int>, а затем отправлю указатель data() на функцию?

Я предполагаю, что выполнение может сработать, если я впоследствии получу доступ к данным, как если бы это был массив, из указателя, но если бы я попытался извлечь эти данные из вектора, используя operator [] размер вектора не будет обновлен, и у меня будут проблемы. Так что я должен просто использовать resize(m), чтобы сделать это.

Ответы [ 4 ]

4 голосов
/ 04 марта 2012

Не делай этого;это неопределенное поведение и просто не допускается.Вместо этого вы должны выполнить почти одинаково дорогую операцию resize(), а затем передать указатель data().

Единственная добавленная стоимость связана с обнулением памяти.К сожалению, нет стандартного контейнера библиотеки, который обрабатывает неинициализированное динамическое хранилище, кроме std::unique_ptr<int[]>(new int[m]).Однако стоимость обнуления очень мала (но концептуально это может раздражать, потому что вы знаете, что собираетесь перезаписать данные).Я предполагаю, что в контексте высокой производительности вы могли бы попробовать подход с уникальным указателем.(Обратите внимание, что массив - new[] для фундаментальных типов обычно полностью эквивалентен ::operator new() или malloc()).

1 голос
/ 04 марта 2012

Правильно, reserve(m) для пустого вектора просто гарантирует, что следующее m push_back() не вызовет перераспределение.Размер вектора по-прежнему останется 0, а запись в выделенные данные запрещена.

Правильный путь здесь - resize(m).

0 голосов
/ 04 марта 2012

reserve изменяет внутренний размер контейнера (так что capacity() теперь больше), но size массива не увеличивается (size() остается таким же, как до вызова). Таким образом, чтобы прямо ответить на ваш вопрос, да , он делает capacity вектора не менее n, где n - это параметр, который вы задали для reserve.

Я не знаю, является ли неопределенным поведение доступа после конца vector, если capacity достаточно велик (но size меньше), когда вы вызываете data() (или делаете *) 1017 *) и получить доступ к массиву через этот указатель. Я не думаю, что это будет неопределенным поведением, если вы используете POD-типы в векторе и не читаете их, прежде чем писать в них. Не пытайтесь делать это с типами классов, потому что элементы за size вектора будут неинициализированы, и их использование будет UB.

Было бы бессмысленно делать это, потому что тогда, когда вы пытаетесь push_back что-то в векторе или вызывать resize для фактического обновления размера, оно перезапишет значения, которые вы подрывно записали в вектор. Просто используйте resize или используйте конструктор vector(int), чтобы установить размер конструкции.

0 голосов
/ 04 марта 2012
void reserve ( size_type n );

Перераспределяет внутренний массив только тогда, когда текущая емкость меньше n .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...