std::thread Why object is copied twice?

c++, c++11

Solution

For anything you want to move or avoid copies, prefer move constructors and `std::move`.

But Why doesn't this happen automatically for me?

Move in C++ is conservative. It generally will only move if you explicitly write `std::move()`. This was done because move semantics, if extended beyond very explicit circumstances, might break older code. Automatic-moves are often restricted to very careful set of circumstances for this reason.

In order to avoid copies in this situation, you need to shift `a` around by using `std::move(a)` (even when passing it into `std::thread`). The reason it makes a copy the first time around is because std::thread can't guarantee that the value will exist after you have finished constructing the std::thread (and you haven't explicitly moved it in). Thusly, it will do the safe thing and make a copy (not take a reference/pointer to what you passed in and store it: the code has no idea whether or not you'll keep it alive or not).

Having both a move constructor and using `std::move` will allow the compiler to maximally and efficiently move your structure. If you're using VC++ (with the CTP or not), you must explicitly write the move constructor, otherwise MSVC will (even sometimes erroneously) declare and use a Copy constructor.

Problem

Why in the example code below, object is copied twice? According documentation constructor of thread class copies all arguments to thread-local storage so we have reason for the first copy. What about second? ``` class A { public: A() {cout << "[C]" << endl;} ~A() {cout << "[~D]" << endl;} A(A const& src) {cout << "[COPY]" << endl;} A& operator=(A const& src) {cout << "[=}" << endl; return *this;} void operator() () {cout << "#" << endl;} }; void foo() { A a; thread t{a}; t.join(); } ``` Output from above: ``` [C] [COPY] [COPY] [~D] # [~D] [~D] ``` Edit: Well yes, after adding move constructor: ``` A(A && src) {cout << "[MOVE]" << endl;} ``` The output is like this: ``` [C] [COPY] [MOVE] [~D] # [~D] [~D] ```

Original source