Áko*_*dra 2 c++ move-semantics c++11
我目前正试图抓住移动构造函数.我发现了以下内容(编译使用g++ d.cpp --std=c++11 -O3)
class A {
string _x;
public:
A(string x) { cout << "default contrsutctor: " << x << "\n"; _x = x; }
A(const A& other) { cout << "copy contrsutctor: " << other._x << "\n"; _x = other._x; }
A(A&& other) { cout << "move contrsutctor: " << other._x << "\n"; _x = other._x; }
A foo() {
cout << "foo: " << _x << "\n";
return A("foo");
}
};
int main()
{
A a;
A b = a;
b.foo();
}
Run Code Online (Sandbox Code Playgroud)
我希望这输出:
default contrsutctor: a
move contrsutctor: a
foo: a
default contrsutctor: foo
Run Code Online (Sandbox Code Playgroud)
但输出是:
default contrsutctor: a
copy contrsutctor: a
foo: a
default contrsutctor: foo
Run Code Online (Sandbox Code Playgroud)
为什么不A b = a优化使用移动构造函数的行?之后永远不会使用a对象,因此优化代码以使用它而不是复制构造函数是安全的.
我知道我可以强制调用移动构造函数std::move(),但我更喜欢在这种情况下自动发生这种情况.
为什么不使用移动构造函数优化A b =一条线?
您可以在复制构造函数和移动构造函数中执行的操作可能完全不同.编译器无法保证两个构造函数的结果相同.实现这种优化有可能改变程序的行为,从而破坏了as-if规则.
您需要使用std::move转换a为A&&:
#include <utility>
int main()
{
A a("a");
A b = std::move(a);
b.foo();
}
Run Code Online (Sandbox Code Playgroud)
移动构造函数的正确实现应该是:
A(A&& other)
: _x(std::move(other._x))
{}
Run Code Online (Sandbox Code Playgroud)
行后A b = std::move(a);,正如@TonyD在评论中指出的那样,a应该是"空".在这种情况下,a._x将是空的.a._str可能处于未指定但有效的状态(移动std:string的构造函数).你应该a在这一行之后谨慎使用.
A b = a;总是调用复制构造函数,无论它是否可以调用移动构造函数.此外,对象的生命周期a在分配后继续,即使它不再使用.
如果要使用移动构造函数,则必须将其显式化:
A b = std::move(a);
Run Code Online (Sandbox Code Playgroud)
请注意,这可能很危险,因为a移动后仍然可以访问.如果您以后意外使用它,可能会有未定义的行为.
想想为什么它应该自动发生.在您给出的示例中,没有必要,因为您可以使用a而不是b.在许多情况下,它会更有意义移动构造函数/赋值将被自动使用,例如A a; a = foo();.