Why std :: vector uses a move constructor, although declared as noexcept (false)

Wherever I read on the Internet, it is highly recommended that if I want my class to work well with std::vector (i.e. the transfer semantics from my class used std::vector ), I should move the constructor move like 'noexcept' (or noexcept(true) ).

Why did std::vector use it, although I marked its noexcept(false) as an experiment?

 #include <iostream> #include <vector> using std::cout; struct T { T() { cout <<"T()\n"; } T(const T&) { cout <<"T(const T&)\n"; } T& operator= (const T&) { cout <<"T& operator= (const T&)\n"; return *this; } ~T() { cout << "~T()\n"; } T& operator=(T&&) noexcept(false) { cout <<"T& operator=(T&&)\n"; return *this; } T(T&&) noexcept(false) { cout << "T(T&&)\n"; } }; int main() { std::vector<T> t_vec; t_vec.push_back(T()); } 

output:

 T() T(T&&) ~T() ~T() 

Why? What have I done wrong?

Compiled on gcc 4.8.2 with CXX_FLAGS installed on:

 --std=c++11 -O0 -fno-elide-constructors 
+6
source share
2 answers

You have done nothing wrong.

You simply mistakenly thought that push_back should have avoided throwing move-ctor: this does not mean, at least, to create a new element.

The only place to throw move-ctors / move-assignments to avoid is to redistribute the vector to avoid moving half of the elements, and the rest in their original places.

The function has a strong guarantee of safety exceptions:

Either the operation succeeds, or it fails and nothing has changed.

+12
source

If vector::push_back needs to redistribute its storage, it first allocates new memory, and then moves the construction of the new element to the last position. If it throws up new memory, is freed, and nothing has changed, you get a strong guarantee of exception safety, even if the move constructor can throw it away.

If it is not thrown away, existing elements are transferred from the source store to the new store, and here the specification of the noexcept move noexcept matters. If the move can be selected and the type is CopyConstructible, then existing elements will be copied, not moved.

But in your test, you only look at how the new element is inserted into the vector, and it is always useful to use the metadata constructor for this step.

+4
source

Source: https://habr.com/ru/post/976323/


All Articles