Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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]
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
275 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...