Ответ 1
Гарантия reserve
заключается в том, что последующие вставки не перераспределяются и, таким образом, не вызывают недействительности. Это. Больше никаких гарантий нет.
У меня есть std::vector
, на котором я называю reserve
большим значением. Впоследствии я извлекаю data()
.
Так как итерация data
затем сбой, мне интересно, разрешено ли это даже. Является ли reserve
принудительно обновлять data
до выделенного диапазона памяти?
Гарантия reserve
заключается в том, что последующие вставки не перераспределяются и, таким образом, не вызывают недействительности. Это. Больше никаких гарантий нет.
Является ли
reserve
принудительно обновлятьdata
до выделенного диапазона памяти?
Нет. Стандарт гарантирует, что std::vector::data
возвращает указатель, а [data(), data() + size())
- допустимый диапазон, capacity
не имеет значения.
$23.3.11.4/1 векторные данные [Vector.data]:
Возвращает: Указатель такой, что
[data(), data() + size())
является действительным ассортимент. Для непустого вектораdata() == addressof(front())
.
Нет требования, чтобы data()
возвращал возвращаемый указатель для пустого (size() == 0
) вектора, даже если он имеет ненулевую емкость. Он может возвращать nullptr
или какое-либо произвольное значение (только в этом случае необходимо, чтобы он мог быть сравним с самим собой, и 0 можно было добавить к нему без вызова UB).
Я бы сказал, что документация довольно понятна в этом разделе: что-нибудь после data() + size()
может быть выделено, но не инициализировано: если вы хотите также инициализировать эту память, вы должны использовать vector::resize
.
void reserve (size_type n);
Запросить изменение емкости
Требует, чтобы векторная емкость была по крайней мере достаточной, чтобы содержать n элементов.
Если n больше текущей емкости вектора, функция вызывает контейнер для перераспределения его хранилища, увеличивающий его емкость до n (или больше).
Во всех остальных случаях вызов функции не вызывает перераспределения и векторная емкость не изменяется.
Эта функция не влияет на размер вектора и не может изменять ее элементы.
Я не уверен, почему вы хотели бы получить доступ к чему-либо после data() + size()
после reserve()
в первую очередь: предполагаемое использование reserve()
заключается в предотвращении ненужных перераспределений, когда вы знаете или можете оценить ожидаемый размер ваш контейнер, но в то же время избегайте ненужного начального объема памяти, который может быть либо неэффективным, либо непрактичным (например, нетривиальные данные для инициализации недоступны). В этой ситуации вы можете заменить log(N)
перераспределения и копии с 1 улучшением производительности.