Подтвердить что ты не робот

Можно ли доверять 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);
}

Является ли это хорошим подходом или мне следует отслеживать размер вектора с независимой переменной?

4b9b3361

Ответ 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() после этого - совершенно правильный подход.