[英]std::move versus copy elision
The following code compiles without warnings in Visual Studio 2019 msvc x64:以下代码在 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:但是,如果我使用 x64-Clang 编译相同的代码,则会收到以下警告:
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? msvc x64 也会复制省略临时变量吗?
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));
}
void f4() {
A tmp = A(5);
a = std::move(tmp);
}
A a;
};
f1, f3 and f4 produce the same sequence of calls to A member functions: f1、f3 和 f4 产生对 A 成员函数的相同调用序列:
default ctor
ctor
move = operator
f2 produce another result: f2 产生另一个结果:
default ctor
ctor
= operator
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
.在任何一种情况下都不能省略,因为这是对
m_thread
的赋值,而不是初始化。 The temporary object must be constructed and then there will be a move assignment from it in either version.必须构造临时 object,然后在任一版本中都会有一个移动分配。
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.提示仍然是正确的,因为
std::move
临时或者根本没有任何效果(如这里),或者如果在允许/强制复制省略的上下文中使用,则防止省略,例如,如果这个是m_thread
的初始化程序,而不是对它的赋值。
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. std::thread(&ThreadRunner::runInThread, this)
是纯右值,通过将其转换为 xvalue,您一无所获。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.