移动构造函数和右值引用是C++11新增的特性,可以减少资源开销,提升效率。
右值引用
首先给一个右值引用声明的例子:
std::string&& r5("Hello World!!");
这里右值引用r5绑定了一个临时变量,临时变量的内容为"Hello World!!",右值引用只可以绑定临时变量也就是右值,而左值(有地址的变量)是不可以的,例如如下操作是允许的:
r5 = "abcdefg";
而如下操作是不允许的:
std::string strtest("Hello World!!");
std::string&& r4{ strtest }; //不可以,strtest是左值
move函数
std::move: 并不能移动任何东西,只是将一个左值强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义,从实现上讲,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue);
移动构造函数
移动构造函数用于当复制构造函数的参数为右引用的时候,之所以叫移动是因为新生成对象并不会重新申请内存,而是会直接使用拷贝对象的内存,而拷贝的对象通过对应指针赋值为NULL,从而失去对原有内存的控制。
实例
下面通过一个实例来说明其工作原理
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
using namespace std;
class Str{
public:
char *str;
Str(char value[])
{
cout<<"origin construct function..."<<endl;
str = NULL;
int len = strlen(value);
str = new char[len + 1];
memset(str,0,len + 1);
strcpy(str,value);
}
Str(const Str &s)
{
cout<<"copy construct function..."<<endl;
str = NULL;
int len = strlen(s.str);
str = new char[len + 1];
memset(str,0,len + 1);
strcpy(str,s.str);
}
Str(Str &&s)
{
cout<<"move construct function..."<<endl;
str = s.str;
s.str = NULL;
}
~Str()
{
cout<<"destruct funciton..."<<endl;
if(str != NULL)
{
delete []str;
str = NULL;
}
}
};
int main()
{
char value[] = "Hello Word!";
cout<<"step 1"<<endl;
Str s(value);
cout<<"step 2"<<endl;
Str ss(move(s));
cout<<"step 3"<<endl;
Str ss1 = ss;
cout<<"step 4"<<endl;
Str ss2 = static_cast<Str&&>(ss1);
cout<<"finish"<<endl;
return 0;
}
结果如下:
step 1
origin construct function...
step 2
move construct function...
step 3
copy construct function...
step 4
move construct function...
finish
destruct funciton...
destruct funciton...
destruct funciton...
destruct funciton...
step1:声明一个类对象,调用原始构造函数即可
step2:由于move将对象变量转换为右值引用,因此调用移动构造函数,可以看下移动构造函数写法,以及如何将内存转为自己的
step3:调用原始复制构造函数
step4:同样调用移动构造函数,可以看到static_cast<T&&>(lvalue)和move函数的作用是一样的。