移动构造函数和拷贝构造函数的
移动构造函数 和 移动赋值运算符 是C++11新引进的特性。
在C++11以前,对象的拷贝主要由三个函数控制: 拷贝构造函数 、 拷贝赋值运算符 、 析构函数 。在C++11引入了 移动构造函数 和 移动赋值运算符 两个函数。
A(A& exp)//拷贝构造函数
{
if(exp.array!=nullptr)
{
int len = strlen(exp.array);
array = new char[len+1];
strcpy(array,exp.array);
}
}
A(A&& exp)//移动构造函数
{
if(exp.array!=nullptr)
{
array = exp.array;
exp.array = nullptr;
}
}
从上可以看出,移动构造函数的传入参数是右值引用,由 && 标出。对于拷贝构造函数,首先会对传入的对象进行一次深拷贝,然后再传给新对象,这样就会产生一次拷贝开销。而对于移动构造函数,首先会把传入对象的地址空间接管,然后将内部所有指针设置为nullptr
,并在原地址上对新对象进行构造,这样就不会产生额外的拷贝开销。
注意: 在传入参数为指针的情况下,因为移动构造函数进行的是浅拷贝,因此在拷贝之后就会有两个指向同一地址空间的指针,在这种情况下,原对象析构之后就会释放掉指针指向的地址空间,这将导致新对象的指针成为野指针,从而引发错误。所以在进行拷贝之后需要将研对象的指针置空,这样在原对象析构的时候就不会释放掉指针指向的地址空间。
移动赋值运算符和拷贝赋值运算符
与移动拷贝函数类似,移动赋值运算符的参数也是一个右值引用,在完成移动操作之后便会被销毁。
A& operator=(A& exp)//拷贝赋值运算符
{
if(this != &exp)
{
free();
if(exp.array!=nullptr)
{
int len = strlen(exp.array);
array = new char[len+1];
strcpy(array,exp.array);
}
}
return *this;
}
A& operator=(A&& exp)//移动赋值运算符
{
if(this!=&exp)
{
free();
array = exp.array;
exp.array = nullptr;
}
return *this;
}
移动语义的出现使得大对象可以避免频繁拷贝造成的性能下降,特别是对于临时对象,移动语义是传递他们的最佳方式!