Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I trust vector::size after an exception is thrown?

Tags:

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?

like image 861
gsamaras Avatar asked May 08 '17 11:05

gsamaras


People also ask

What happens when throw exception?

When an exception is thrown using the throw keyword, the flow of execution of the program is stopped and the control is transferred to the nearest enclosing try-catch block that matches the type of exception thrown. If no such match is found, the default exception handler terminates the program.

Does vector erase change the size?

Yes, size is decreased as you erase elements. Returns the number of elements in the vector.

What happens when a vector goes out of scope?

In this case, all the elements are deleted, but the name of the vector is not deleted. The second way to delete a vector is just to let it go out of scope. Normally, any non-static object declared in a scope dies when it goes out of scope. This means that the object cannot be accessed in a nesting scope (block).

Can we give size to vector?

We can set the size of a Vector using setSize() method of Vector class. If new size is greater than the current size then all the elements after current size index have null values. If new size is less than current size then the elements after current size index have been deleted from the Vector.


2 Answers

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.

like image 81
Quentin Avatar answered Oct 03 '22 15:10

Quentin


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 any InputIterator operation there are no effects. If an exception is thrown while inserting a single element at the end and T is CopyInsertable or is_­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.

like image 39
jotik Avatar answered Oct 03 '22 15:10

jotik