移动构造函数
C++ 移动构造函数
在
#include <iostream>
using namespace std;
class demo{
public:
demo():num(new int(0)){
cout<<"construct!"<<endl;
}
//拷贝构造函数
demo(const demo &d):num(new int(*d.num)){
cout<<"copy construct!"<<endl;
}
~demo(){
cout<<"class destruct!"<<endl;
}
private:
int *num;
};
demo get_demo(){
return demo();
}
int main(){
demo a = get_demo();
return 0;
}
如上所示,我们为
- 执行
get_demo() 函数内部的demo() 语句,即调用demo 类的默认构造函数生成一个匿名对象; - 执行
return demo() 语句,会调用拷贝构造函数复制一份之前生成的匿名对象,并将其作为get_demo() 函数的返回值(函数体执行完毕之前,匿名对象会被析构销毁) ; - 执行
a = get_demo() 语句,再调用一次拷贝构造函数,将之前拷贝得到的临时对象复制给a (此行代码执行完毕,get_demo() 函数返回的对象会被析构) ; - 程序执行结束前,会自行调用
demo 类的析构函数销毁a 。
注意,目前多数编译器都会对程序中发生的拷贝操作进行优化,因此如果我们使用
construct!
class destruct!
而同样的程序,如果在g++ demo.cpp -fno-elide-constructors
命令运行,就可以看到完整的输出结果:
construct! <-- 执行 demo()
copy construct! <-- 执行 return demo()
class destruct! <-- 销毁 demo() 产生的匿名对象
copy construct! <-- 执行 a = get_demo()
class destruct! <-- 销毁 get_demo() 返回的临时对象
class destruct! <-- 销毁 a
如上所示,利用拷贝构造函数实现对
使用移动构造函数复写
所谓移动语义,指的就是以移动而非深拷贝的方式初始化含有指针成员的类对象。简单的理解,移动语义指的就是将其他对象(通常是临时对象)拥有的内存资源“移为已用”。以前面程序中的
事实上,对于程序执行过程中产生的临时对象,往往只用于传递数据(没有其它的用处
#include <iostream>
using namespace std;
class demo{
public:
demo():num(new int(0)){
cout<<"construct!"<<endl;
}
demo(const demo &d):num(new int(*d.num)){
cout<<"copy construct!"<<endl;
}
//添加移动构造函数
demo(demo &&d):num(d.num){
d.num = NULL;
cout<<"move construct!"<<endl;
}
~demo(){
cout<<"class destruct!"<<endl;
}
private:
int *num;
};
demo get_demo(){
return demo();
}
int main(){
demo a = get_demo();
return 0;
}
可以看到,在之前g++ demo.cpp -o demo.exe -std=c++0x -fno-elide-constructors
命令执行此程序,输出结果为:
construct!
move construct!
class destruct!
move construct!
class destruct!
class destruct!
通过执行结果我们不难得知,当为