编译: g++ --std=c++11 -g -fno-elide-constructors -O0 test.cc -o test
-fno-elide-constructors 用来关闭编译器优化
#include <iostream>
class A {
public:
A(const int &value) {
_value = value;
std::cout << "Contructor value: " << _value << std::endl;
}
~A() {
std::cout << "Destructor value: " << _value << std::endl;
}
// 拷贝构造函数
A(const A &a) : _value(a._value) {
std::cout << "Copy Contructor value: " << _value << std::endl;
}
// 移动构造函数
A(A &&a) : _value(a._value) {
std::cout << "Move Contructor value: " << _value << std::endl;
}
private:
int _value;
};
-
定义了移动构造函数的情况下:
- 第一种情况:
A test() { A a(10); return a; } int main(void) { A a = test(); return 0; }
编译运行结果:
Contructor value: 10 Move Contructor value: 10 Destructor value: 10 Move Contructor value: 10 Destructor value: 10 Destructor value: 10
- 第二种情况:
A test() { A a(10); return a; } int main(void) { A &&a = test(); return 0; }
编译运行结果:
Contructor value: 10 Move Contructor value: 10 Destructor value: 10 Destructor value: 10
- 第三种情况:
A &&test() { A a(10); return std::move(a); } int main(void) { A &&a = test(); return 0; }
编译运行结果:
Contructor value: 10 Destructor value: 10
- 第四种情况:
A &&test() { A a(10); return std::move(a); } int main(void) { A a = test(); return 0; }
编译运行结果:
Contructor value: 10 Destructor value: 10 Move Contructor value: -374511968 Destructor value: -374511968
- 第五种情况:
A &&test() { A a(10); return std::move(a); } int main(void) { A a = test(); return 0; }
编译运行结果:
Contructor value: 10 Destructor value: 10
-
没有定义移动构造函数的情况下:
- 同样五种情况的运行结果如下:
Contructor value: 10 Copy Contructor value: 10 Destructor value: 10 Copy Contructor value: 10 Destructor value: 10 Destructor value: 10
Contructor value: 10 Copy Contructor value: 10 Destructor value: 10 Destructor value: 10
Contructor value: 10 Destructor value: 10
Contructor value: 10 Destructor value: 10 Copy Contructor value: -298764640 Destructor value: -298764640
Contructor value: 10 Destructor value: 10
当类中同时包含拷贝构造函数和移动构造函数时,如果使用临时对象初始化当前类的对象,编译器会优先调用移动构造函数来完成此操作。只有当类中没有合适的移动构造函数时,编译器才会退而求其次,调用拷贝构造函数。
默认情况下,左值初始化同类对象只能通过拷贝构造函数完成,如果想调用移动构造函数,则必须使用右值进行初始化。C++11 标准中为了满足用户使用左值初始化同类对象时也通过移动构造函数完成的需求,新引入了 std::move() 函数,它可以将左值强制转换成对应的右值,由此便可以使用移动构造函数。