Насколько я понял стандарт (хотя на самом деле я не мог назвать ссылку), создание экземпляра контейнера и выделение памяти были намеренно отделены друг от друга по уважительной причине. Поэтому у вас есть четкие, отдельные призывы к
constructor
создать сам контейнер
reserve()
предварительно выделить достаточно большой блок памяти для размещения хотя бы (!) заданного количества объектов
И в этом есть большой смысл. Единственное право на существование reserve()
- дать вам возможность кодировать возможно дорогостоящее перераспределение при наращивании вектора. Чтобы быть полезным, вы должны знать количество объектов, которые нужно хранить, или, по крайней мере, уметь делать обоснованное предположение. Если этого не происходит, лучше держитесь подальше, так reserve()
как вы просто измените перераспределение потраченной впустую памяти.
Итак, сложим все вместе:
- Стандарт намеренно не определяет конструктор, который позволяет вам предварительно выделить блок памяти для определенного количества объектов (что было бы, по крайней мере, более желательно, чем выделение фиксированного «чего-то» для конкретной реализации под капотом).
- Распределение не должно быть подразумеваемым. Итак, чтобы предварительно выделить блок, вам нужно сделать отдельный вызов,
reserve()
и он не обязательно должен находиться в том же месте строительства (может / должен, конечно, быть позже, после того, как вы узнали о необходимом размере для размещения)
- Таким образом, если вектор всегда будет заранее выделять блок памяти размера, определенного реализацией, это сорвало бы намеченную работу
reserve()
, не так ли?
- В чем будет преимущество предварительного выделения блока, если STL, естественно, не может знать предполагаемое назначение и ожидаемый размер вектора? Это будет довольно бессмысленно, если не сказать контрпродуктивно.
- Вместо этого правильным решением является выделение и реализация конкретного блока с первым
push_back()
- если это еще не было явно выделено ранее reserve()
.
- В случае необходимого перераспределения увеличение размера блока также зависит от реализации. Известные мне реализации векторов начинаются с экспоненциального увеличения размера, но будут ограничивать скорость приращения до определенного максимума, чтобы не тратить впустую огромное количество памяти или даже не испортить ее.
Все это работает в полной мере и приносит пользу только в том случае, если его не нарушает конструктор размещения. У вас есть разумные значения по умолчанию для общих сценариев, которые могут быть отменены по запросу с помощью reserve()
(и shrink_to_fit()
). Итак, даже если в стандарте это явно не указано, я вполне уверен, что предположение, что вновь созданный вектор не распределяется заранее, является довольно безопасной ставкой для всех текущих реализаций.