#include <iostream>
class C {
public:
~C() { std::cout << this << " destructor\n"; }
C() { std::cout << this << " constructor\n"; }
C(C&& rhs) {
std::cout << &rhs << " rhs\n";
std::cout << this << " move constructor\n";
}
C& operator=(C&& rhs) {
std::cout << &rhs << " rhs\n";
std::cout << this << " move assignment\n";
return *this;
}
};
C make_one() {
C tmp;
return tmp;
}
int main() {
std::cout << "move constructor:\n";
C c1(make_one());
std::cout << &c1 << " &c1\n\n";
std::cout << "move assignment:\n";
C c2;
c2 = make_one();
...
}
Run Code Online (Sandbox Code Playgroud)
输出:
move constructor:
000000000021F9B4 constructor // tmp constructed in make_one()
000000000021F9B4 rhs // return triggers tmp being passed to ...
000000000021FA04 move constructor // ... c1's move constructor (see below)
000000000021F9B4 destructor // tmp destructs on going out of scope
000000000021FA04 &c1 // (confirmed c1's address)
move assignment:
000000000021FA24 constructor // c2 constructed
000000000021F9B4 constructor // tmp constructed in make_one() again
000000000021F9B4 rhs // tmp passed to ...
000000000021FA34 move constructor // ... a new object's move constructor
000000000021F9B4 destructor // tmp destructs on going out of scope
000000000021FA34 rhs // new object passed to ...
000000000021FA24 move assignment // .. c2's move assignment operator
000000000021FA34 destructor // new object destructs
...
Run Code Online (Sandbox Code Playgroud)
移动分配似乎首先触发移动构造函数并创建一个额外的对象.这是正常的吗?我希望(通过类比复制赋值)将tmp直接传递给c2的移动赋值.
[Visual Studio Express 2013]
"额外对象"称为返回值.从函数返回值时; 此值是从您提供给return语句的值构造的复制/移动.
通常这会经历复制省略,这可以解释为什么你不认识它.当复制省略发生时,该行C tmp;实际上将tmp直接构造为返回值.复制省略也可以在其他一些情况下发生; 有关全文,请参阅C++ 11 [class.copy]#31.
大概你可以在这里手动禁用复制省略,或者编译器决定不执行复制省略是个好主意.更新:您的编译器仅在发布版本上执行此特定的copy-elision - 感谢Praetorian