Reputation: 73384
I am trying to understand how exceptions affect an std::vector
. More precisely, I want to check the size of the vector, when an out of memory exception is thrown.
I mean something like this:
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);
}
Is that a good approach or should I keep track of the vector's size with an independent variable of mine?
Upvotes: 22
Views: 2468
Reputation: 69
Exceptions If an exception is thrown (which can be due to Allocator::allocate() or element copy/move constructor/assignment), this function has no effect (strong exception guarantee).
If T's move constructor is not noexcept and T is not CopyInsertable into *this, vector will use the throwing move constructor. If it throws, the guarantee is waived and the effects are unspecified.
Upvotes: 1
Reputation: 17910
According to [vector.modifiers] (emphasis mine):
Remarks: Causes reallocation if the new size is greater than the old capacity. Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. If no reallocation happens, all the iterators and references before the insertion point remain valid. If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of
T
or by anyInputIterator
operation there are no effects. If an exception is thrown while inserting a single element at the end andT
isCopyInsertable
oris_nothrow_move_constructible_v<T>
is true, there are no effects. Otherwise, if an exception is thrown by the move constructor of a non-CopyInsertable
T
, the effects are unspecified.
Since your T
is int
(and operations on integers never throw) you can only get the out-of-memory errors from std::vector
when it attempts to allocate new memory for its contents, hence this function has no effect when throwing any exception and using size()
afterwards is a perfectly valid approach.
Upvotes: 11
Reputation: 63144
From the documentation for std::vector::push_back
:
If an exception is thrown (which can be due to
Allocator::allocate()
or element copy/move constructor/assignment), this function has no effect (strong exception guarantee).
So in case of failure, the last push_back
which caused the exception will be rolled back, but everything else will be fine: your vector will contain all of the previously pushed elements, and will be in a consistent state.
Upvotes: 31