Наскільки я зрозумів стандарт (хоча я насправді не міг назвати посилання), інстанція контейнера та розподіл пам'яті навмисно роз'єднані з поважних причин. Тому у вас є окремі окремі дзвінки
constructor
щоб створити сам контейнер
reserve()
попередньо виділити відповідний великий блок пам'яті для розміщення принаймні (!) заданої кількості об'єктів
І в цьому є великий сенс. Єдине право існувати для reserve()
- це дати вам можливість кодувати навколо можливо дорогих перерозподілів при зростанні вектора. Для того, щоб бути корисним, ви повинні знати кількість предметів, які потрібно зберігати, або, принаймні, потрібно мати змогу зробити освічені здогади. Якщо цього не зробити, вам краще триматися подалі, reserve()
оскільки ви просто зміните перерозподіл на марну пам'ять.
Тож склавши все разом:
- Стандарт навмисно не вказує конструктор, який дозволяє попередньо виділити блок пам'яті для певної кількості об'єктів (що було б принаймні більш бажаним, ніж виділення конкретної реалізації, фіксованого "чогось" під капотом).
- Розподіл не повинен бути неявним. Отже, для попереднього розподілу блоку вам потрібно зробити окремий дзвінок,
reserve()
і це не повинно знаходитись у тому самому місці будівництва (може, звичайно, пізніше, після того, як ви дізнаєтесь про необхідний розмір для розміщення)
- Таким чином, якщо вектор завжди буде попередньо розподіляти блок пам’яті реалізації визначеного розміру, це буде перешкоджати запланованій роботі
reserve()
, чи не так?
- Яка була б перевага попереднього розподілу блоку, якщо STL, природно, не може знати цільового призначення та очікуваного розміру вектора? Це буде досить безглуздо, якщо не контрпродуктивно.
- Натомість правильним рішенням є виділення та реалізація конкретного блоку з першим
push_back()
- якщо він ще не був явно виділений раніше reserve()
.
- У разі необхідного перерозподілу збільшення розміру блоку також є специфічним для реалізації. Я знаю, що векторні реалізації починаються з експоненціального збільшення розміру, але обмежують швидкість приросту на певному максимумі, щоб уникнути втрати величезної кількості пам'яті або навіть її продування.
Все це призводить до повноцінної роботи та переваг, лише якщо це не порушено розподіляючим конструктором. У вас є розумні значення за замовчуванням для типових сценаріїв, які можуть бути замінені на вимогу reserve()
(та shrink_to_fit()
). Отже, навіть якщо стандарт не передбачає це явно, я впевнений, що припущення, що нещодавно побудований вектор не попередньо розподіляє, є досить безпечним вибором для всіх поточних реалізацій.