http://stackoverflow.com/questions/3106110/what-is-move-semantics/
解释了 move 语义。非常清楚。
我主要是想测试一下move语义是否真正生效了。
1. move构造函数在何种情况下会被调用
2. 编译器神马时候会合成默认的move构造函数
3. 对于包含了其他成员的类来说,对于被包含的对象来说,move语句在神马情况下是生效的。
比如说,B 中有 A 类型的对象,那么,在调用 B 的move构造函数的时候,A的move构造函数是否会被调用。
#include <iostream>
using namespace std;
class A {
public:
A() {}
A(const A& lv) { cout << "a copy ctor." << endl; }
A(A&& rv) { cout << "a move ctor." << endl; }
};
class B {
public:
B() {}
B(int ia) {}
// B(const B& lv) : a(lv.a) { cout << "b copy ctor." << endl; } // 1
// B(B&& rv) : a(std::move(rv.a)) { cout << "b move ctor." << endl; } // 2
// B(B&& rv) : a(rv.a) { cout << "b move ctor." << endl; } // 3
// B(B&& rv) = default; // 4
private:
A a;
};
int main() {
B b;
B b1(b);
cout << "111" << endl;
B b2(std::move(b));
}
以上程序在 g++ 4.8.1上编译
case A:
1,2,3,4全部被注释的输出结果:a copy ctor.
111
a move ctor.
猜测原因:
编译器自己合成了B的copy和move构造函数,并且,在B的move构造函数中调用了A的move构造函数。
case B:
取消1的注释,2,3,4注释掉:
a copy ctor.
b copy ctor.
111
a copy ctor.
b copy ctor.
猜测原因:
编译器没有合成 B的默认move构造函数,并且,即使用户将变量 b std::move化,调用的也是B的copy构造函数。
因为用户自己定义了B的copy构造函数,所以编译器会认为,你自己管理了资源,所以就不敢随便编写一个move构造函数了。
cpp标准 12.8 节规定了编译器隐式定义move构造函数的条件:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
case C:
取消1,2的注释,3,4注释掉:
a copy ctor.
b copy ctor.
111
a move ctor.
b move ctor.
猜测原因:
就是都定义了,所以调用对应的move或者copy而已。
case D:
取消1,3注释,2,4注释掉:
a copy ctor.
b copy ctor.
111
a copy ctor.
b move ctor.
猜测原因:
注意,在b的move构造函数中,调用的是a的copy构造函数。
这里的原因是 rv 的类型虽然是右值引用,但其自身是左值,如果要利用右值引用的优势,需要对 rv move化:
如改成这样就会调用 a 的 move 构造函数: B(B&& rv) : a(std::move(rv).a) { cout << "b move ctor." << endl; }
或者像例子 2 中的那样,对 rv 的每一个成员进行 move 化。
case E:
取消1,4的注释,2,3注释掉:
a copy ctor.
b copy ctor.
111
a move ctor.
猜测原因:
显示指定了move构造函数为default,此构造函数调用了a的move构造函数。
case F:
取消4的注释,只保留1,2,3:
编译不通过。
move_.cpp: In function ‘int main()’:
move_.cpp:26:9: error: use of deleted function ‘B::B(const B&)’
B b1(b);
^
move_.cpp:12:7: note: ‘B::B(const B&)’ is implicitly declared as deleted because ‘B’ declares a move constructor or move assignment operator
class B {
原因是因为已经定义 move 构造函数,所以copy构造函数默认声明为了 delete。
这个规则在cpp标准中也是规定了的。
啊,暂时先写这么点。。