2

Consider:

struct Boo { Boo (std::string v) : src {v} {} Boo (const Boo&) = delete; Boo& operator= (const Boo&) = delete; Boo (Boo&& b) : src {std::move (b.src)} {} Boo& operator= (Boo&& b) { if (this != &b) { foo (); src = std::move (b.src); } return *this; } void show () { std::cout << "|" << src << "|" << std::endl; } void foo () { throw 1; } std::string src {}; }; 

and usage:

int main(int argc, char** argv) { Boo s {"Boo1"}; Boo p {"Boo2"}; try { p = std::move (s); // (X) } catch (...) {} s.show (); p.show (); return 0; } 

And outputs look like this:

If foo() is invoked in move assignment operator

|Boo1| |Boo2| 

If foo() is not invoked

|Boo2| |Boo1| 

Questions:

What happens with s when exception is thrown in move assignment operator? Does it have previous content just like before using std::move() in line (X), or the content is completely moved to the b (function parameter)?

Why in both cases outputs show that content is still in std::string objects?

3
  • If you want to see performance gains from move-semantics in STL containers, you will have to use noexcept because otherwise the STL will just copy the objects to prevent inconsistent state. Commented Dec 21, 2015 at 15:34
  • @Jens Where is that described? Commented Dec 21, 2015 at 16:00
  • @DieterLücking The statement may be too broad. Containers have move semantics independent from the element type, but other operations like resize only use move-semantics if it is nothrow. I couldn't find an explicit definition for this, but it follows from the defined semantics in case an exception occurs. Then, resize must restore the old state of the vector, but that cannot be done when the (destructive) move threw. So, resize can only use nothrow move. There is a special helper move_if_noexcept defined in the standard for this: en.cppreference.com/w/cpp/utility/move_if_noexcept. Commented Dec 21, 2015 at 16:28

1 Answer 1

3

When an exception is thrown, normal execution halts immediately, and the call stack is unwound. until the first valid catch. For your case it means that as soon as you throw the continued execution of the foo and the assignment operator functions are halted and the program goes to the catch in the main function, in other words nothing happens that would alter the objects.

Moving a std::string object leaves the source in a valid but uspecified state. It should be noted that moving is commonly implemented by swapping source and destination, which will explain the behavior you see.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.