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.
