移动构造函数的触发有个前提,就是构造时需要基于一个临时对象。
标准库提供了move函数,可以把一个左值转换为右值,从而可以触发移动构造函数。
#include <iostream>
using namespace std;
class A{
public:
A()
{
m_i = new int(1);
cout<<"Construct A, this addr:"<<this<<", m_i addr:"<<m_i<<endl;
}
A(const A &a):m_i(new int(*a.m_i))
{
cout<<"Copy Construct A, ori addr:"<<&a<<" ori m_i addr:"<<a.m_i<<" *m_i="<<*a.m_i<<", this addr:"<<this<<" m_i addr:"<<m_i<<" *a.m_i="<<*a.m_i<<endl;
}
A(A&& a):m_i(a.m_i)//移动构造函数接受一个所谓的“右值引用”的参数,完成资源的转移
{
cout<<"Move Construct A, ori addr:"<<&a<<" ori m_i addr:"<<a.m_i<<" *m_i="<<*a.m_i<<", this addr:"<<this<<" m_i addr:"<<m_i<<" *a.m_i="<<*a.m_i<<endl;
a.m_i = 0;
}
~A()
{
cout<<"Destruct A, this addr:"<<this<<" m_i addr:"<<m_i<<endl;
if(m_i)
{
free(m_i);
m_i = 0;
}
}
int *m_i;
};
int main(){
A a1; //通过默认构造函数构造对象a1
A a2 = move(a1); //通过move,将a1转换为右值,从而触发移动构造函数,构造对象a2
cout<<"a2 addr:"<<&a2<<" a2.m_i addr:"<<a2.m_i<<" *a2.m_i="<<*a2.m_i<<endl;
return 0;
}
运行程序输出:
//构造对象a1
Construct A, this addr:0x63fe08, m_i addr:0x7a6f90
//将a1转换为右值,从而触发移动构造函数,构造对象a2
Move Construct A, ori addr:0x63fe08 ori m_i addr:0x7a6f90 *m_i=1, this addr:0x63fe00 m_i addr:0x7a6f90 *a.m_i=1
//a2的成员m_i指向的地址与a1.m_i相同
a2 addr:0x63fe00 a2.m_i addr:0x7a6f90 *a2.m_i=1
//a2析构
Destruct A, this addr:0x63fe00 m_i addr:0x7a6f90
//a1析构
Destruct A, this addr:0x63fe08 m_i addr:0