Можно ли доверять vector:: size после того, как будет выбрано исключение?
Я пытаюсь понять, как исключения влияют на std::vector
. Точнее, я хочу проверить размер вектора, когда выбрано исключение из памяти.
Я имею в виду что-то вроде этого:
std::vector<int> v;
try {
for(unsigned int i = 0; i < desiredSize; ++i)
v.push_back(i);
}
catch (const std::bad_alloc&) {
cerr << "Out of memory! v.size() = " << v.size() << endl;
exit(EXIT_FAILURE);
}
Является ли это хорошим подходом или мне следует отслеживать размер вектора с независимой переменной?
Ответы
Ответ 1
Из документация для std::vector::push_back
:
Если генерируется исключение (что может быть связано с Allocator::allocate()
или конструктором/присваиванием элемента copy/move), эта функция не действует (сильная гарантия исключения).
Таким образом, в случае отказа последний push_back
, который вызвал исключение, будет откат, но все остальное будет в порядке: ваш вектор будет содержать все ранее перенесенные элементы и будет находиться в согласованном состоянии.
Ответ 2
Согласно [vector.modifier] (выделение):
Примечания: вызывает перераспределение, если новый размер больше старой. Перераспределение делает недействительными все ссылки, указатели и итераторы, ссылающиеся на элементы в последовательности. Если перераспределение не происходит, все итераторы и ссылки до точки вставки остаются в силе. Если исключение выбрано иначе, чем конструктор копирования, переместите конструктор, оператор присваивания или оператор присваивания перемещения T
или какой-либо операции InputIterator
нет эффектов.Если исключение генерируется при вставке одного элемента в конец, а T
- CopyInsertable
или is_nothrow_move_constructible_v<T>
- true, эффектов нет. В противном случае, если исключение вызывается конструктором перемещения не CopyInsertable
T
, эффекты не заданы.
Так как ваш T
int
(и операции с целыми числами никогда не бросаются), вы можете получить только ошибки из памяти std::vector
, когда он пытается выделить новую память для своего содержимого, поэтому эта функция имеет никакой эффект при бросании каких-либо исключений и использовании size()
после этого - совершенно правильный подход.