Home > Mobile >  std::move versus copy elision
std::move versus copy elision

Time:01-18

The following code compiles without warnings in Visual Studio 2019 msvc x64:

class ThreadRunner {
public:
    void start() {
        m_thread = std::move(std::thread(&ThreadRunner::runInThread, this));
    }
    
private:
    void runInThread() {
        for (int i = 0; i < 1000 * 1000; i  ) {
            std::cout << "i: " << i << "\n";
        }
    };
    std::thread m_thread;
};

However if I compile the same code with x64-Clang I get the following warning:

warning : moving a temporary object prevents copy elision [-Wpessimizing-move]

Does this mean that I should have written:

m_thread = std::thread(&ThreadRunner::runInThread, this);

instead? And the compiler would have optimized away ("copy elided") the temporary variable?

Will msvc x64 also copy elide the temporary variable?

I did an experiment:

struct B {
    void f1() {
        a = A(5);
    }
    void f2() {
        A tmp = A(5);
        a = tmp;
    }
    void f3() {
        a = std::move(A(5));
    }
    A a;
};

f1 and f3 produce the same sequence of calls to A member functions:

default ctor
ctor
move = operator

f2 produce another result:

default ctor
ctor
= operator

CodePudding user response:

Does this mean that I should have written:

m_thread = std::thread(&ThreadRunner::runInThread, this);

instead?

Yes, it means that and you should have. std::thread(&ThreadRunner::runInThread, this) is a prvalue, and you gain nothing by casting it to an xvalue.

CodePudding user response:

The two versions

m_thread = std::thread(&ThreadRunner::runInThread, this);

and

m_thread = std::move(std::thread(&ThreadRunner::runInThread, this));

behave identically. No elision is possible in either case, since this is assignment to, not initialization of, m_thread. The temporary object must be constructed and then there will be a move assignment from it in either version.

The hint is still correct though, since std::move on a temporary either doesn't have any effect at all (as here) or prevents elision if used in a context where copy elision would otherwise be allowed/mandatory, for example if this was the initializer of m_thread instead of an assignment to it.

  •  Tags:  
  • Related