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

Categories

0 votes
273 views
in Technique[技术] by (71.8m points)

c++ - std::thread Why object is copied twice?

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

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

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...