Consider the following program:
#include <vector> #include <iostream> class A { int x; public: A(int n) noexcept : x(n) { std::cout << "ctor with value\n"; } A(const A& other) noexcept : x(other.x) { std::cout << "copy ctor\n"; } A(A&& other) noexcept : x(other.x) { std::cout << "move ctor\n"; } ~A() { std::cout << "dtor\n"; } // (*) }; int main() { std::vector<A> v; v.emplace_back(123); v.emplace_back(456); } If I run the program, I get (GodBolt):
ctor with value ctor with value move ctor dtor dtor dtor ... which is in line with what I would expect. However, if on line (*) I mark the destructor as potentially throwing, I then get :
ctor with value ctor with value copy ctor dtor dtor dtor ... i.e. the copy ctor is used instead of the move ctor. Why is this the case? It doesn't seem copying prevents destructions that moving would necessitate.
Related questions:
noexcept. This question asks why copy constructor is chosen if destructor can throw exceptions.noexceptspecifier behaves like this. Here the question is about the case with anoexceptspecifier. So I'll reopen.std::vector.