C++11支持移动语义。
一:为什么需要移动语义和什么是移动语义
我们先来看看C++11之前的复制过程。假设有下列代码:
vector
vector
vector和string类都使用动态内存分配,因此他们必须定义使用他们自己的new版本的复制构造函数。
复制构造函数vector
但真的没有问题吗?有时候答案是否定的。例如,假设有一个函数,他返回一个vector
vector
vector
//复制100W个string到temp
return temp;
}
接下来,以以下方式调用这个函数。
vector
vector
构造v2的时候,编译器先利用v1构造生成了一个temp副本,然后将temp复制给一个临时对象,返回给v2,v2利用该临时对象,构造自己。
这将导致非常巨大的工作量!做了大量的无用功(将temp复制给一个临时对象,返回给v2,v2利用该临时对象,构造自己)。在这之后,temp这个临时的对象被删除了,返回的那个temp副本临时对象也被删除了,如果编译器能够将temp的所有权直接转移给v2不是更好吗?也就是说,不用将100W个string多次复制到新的地方,再删除原来的字符,而是直接保留字符,并将v2与之关联。这类似于计算机中文件的移动。实际文件还保留在原来的地方,而只是记录修改了,这种方法称之为移动语义。
移动语义避免了移动原始数据,而只是修改了记录。
要实现移动语义,必须让编译器知道什么时候需要复制,什么时候不需要复制。这就是右值引用发挥最大作用的地方。
二:如何实现移动语义
看一个简单的使用移动语义的例子。
#includeusing namespace std; class A{ private: int data;//data int *pi;//point to data public: //禁止隐式转换 A(){ } explicit A(int i):data(i){ cout<<"normal constuctor1!"< A(const A &a){ data=a.data; cout<<"copy constructor!"<
看出来什么问题没有?
对,好像并没有调用移动构造函数!<??http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+tavKx9PQw7vT0Leiz9YhdGVtcLrNZLXEcGm2vMrH1rjP8s2s0ru49rXYt73Ex7j2P9XiysfKssO0x+m/9j88L3A+CjxwPtStwLTKx9LyzqpHQ0PX1LT4tcTT0iYjMjA1NDA70+/S5SE8L3A+CjxwPtKyvs3Kxyyx4NLrxvdHQ0O74bDvxOPX1Lav08W7ryE8L3A+CjxwPrK70MXH67+0z8LD5sD919MhztLDx8D708NDJiM0MzsmIzQzOzExtcRkZWxldGXM2NDUITwvcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">#include
using namespace std; class A{ private: int data;//data int *pi;//point to data public: //禁止隐式转换 A(){ } explicit A(int i):data(i){ cout<<"normal constuctor1!"<
运行结果:
也就是说,在return temp;这一句上将要调用A(A&&)这个构造函数;
但是现在这个函数被我们显式删除了!
b+c也是一个右值!也是需要调用移动构造函数的!
因此上一个例子实际上是调用了移动语义的构造函数!

