Предисловие (это может быть длинным, но очень важным)
Вы можете сказать, что «значения мусора» приемлемы, но это не так. Потому что, когда люди говорят, что в их коде C ++ есть значения мусора, которых они на самом деле не имеют, они фактически имеют неопределенное поведение. И вы не должны воспринимать слегка неопределенное поведение. Позвольте мне процитировать из другого моего ответа :
void foo();
void bar();
void test(bool cond)
{
int a; // uninitialized
if (cond)
a = 24;
if (a == 24)
foo();
else
bar();
}
Каков результат вызова вышеуказанной функции с true
? Как насчет false
?
test(true)
, будет очищен вызов foo()
.
Как насчет test(false)
? Если вы ответите: «Ну, это зависит от того, что значение мусора находится в переменной a
, если это 24
, это вызовет foo
, иначе это вызовет bar
» Тогда вы полностью неправильно.
Если вы вызываете test(false)
, программа обращается к неинициализированной переменной и имеет неопределенное поведение, это недопустимый путь, и поэтому компиляторы могут предполагать, что cond
никогда не будет false
(потому что в противном случае программа была бы нелегальной). И неожиданный сюрприз, и g cc, и clang с включенными оптимизациями фактически делают это, и генерирует эту сборку для функции:
test(bool):
jmp foo()
Мораль этой истории заключается в том, что UB - это UB. Не полагайтесь на какое-либо поведение. Доступ к неинициализированным переменным или памяти не приводит к значениям мусора , это приводит к UB, и результаты могут быть очень плохими, чрезвычайно удивительными и трудными для отладки.
Возвращаясь к Ваш вопрос: нет, в std::vector
нет способа выделить неинициализированную память, к которой у вас есть доступ. Т.е. это UB, и вы на 100% не должны этого делать:
std::vector<int> v = ...;
v.reserve(v.size() + 100);
v[v.size()] = 11; // Access beyond vector's size,
// Undefined Behavior even if you reserved memory for it
Я знаю, что установка длины, превышающей емкость вектора, является неопределенным поведением
Нет, это не так:
std :: vector :: resize
void resize( size_type count );
Изменяет размер контейнера, чтобы в нем содержалось количество элементов.
Если текущий размер меньше количества, добавляются дополнительные вставленные по умолчанию элементы
Конечно, недостатком является то, что элементы будут вставлены по умолчанию. Но, как я уже сказал, в std:::vector
обойти это невозможно. Теоретически невозможно сделать даже без std::vector
. Существует длительная проблема с правилами жизни объектов в C ++ (даже несмотря на то, что де-факто это игнорируется на практике). Есть бумага p0593r2 , которая пытается решить эту проблему. Но даже с решением, принятым в стандарте, вам все равно придется реализовать свой собственный контейнер, чтобы разрешать и делать то, что вы хотите.