C++11支持移动语义。ios
一:为何须要移动语义和什么是移动语义函数
咱们先来看看C++11以前的复制过程。假设有下列代码:优化
vector<string> v1(1000000);//v1存放着100W个string,假设每一个string长度为1000spa
vector<string> v2(v1);//使用v1初始化v2.net
vector和string类都使用动态内存分配,所以他们必须定义使用他们本身的new版本的复制构造函数。code
复制构造函数vector<string>将使用new给1000W个string分配对象,而每一个string 将使用new给每一个string分配1000个字符的空间大小。接下来所有的都将从v1中逐个复制string到v2中,这里的工做量很是大,可是并无问题。orm
但真的没有问题吗?有时候答案是否认的。例如,假设有一个函数,他返回一个vector<string>对象。对象
vector<string>copyVector(const vector<string> &v){blog
vector<string> temp;ip
//复制100W个string到temp
return temp;
}
接下来,以如下方式调用这个函数。
vector<string> v1(1000000);//v1存放着100W个string,假设每一个string长度为1000
vector<string> v2=copyVector(v1);//使用v1初始化v2
构造v2的时候,编译器先利用v1构造生成了一个temp副本,而后将temp复制给一个临时对象,返回给v2,v2利用该临时对象,构造本身。
这将致使很是巨大的工做量!作了大量的无用功(将temp复制给一个临时对象,返回给v2,v2利用该临时对象,构造本身)。在这以后,temp这个临时的对象被删除了,返回的那个temp副本临时对象也被删除了,若是编译器可以将temp的全部权直接转移给v2不是更好吗?也就是说,不用将100W个string屡次复制到新的地方,再删除原来的字符,而是直接保留字符,并将v2与之关联。这相似于计算机中文件的移动。实际文件还保留在原来的地方,而只是记录修改了,这种方法称之为移动语义。
移动语义避免了移动原始数据,而只是修改了记录。
要实现移动语义,必须让编译器知道何时须要复制,何时不须要复制。这就是右值引用发挥最大做用的地方。
二:如何实现移动语义
看一个简单的使用移动语义的例子。
56 }
运行截图:
看出来什么问题没有?
对,好像并无调用移动构造函数!
可是有没有发现!temp和d的pi都是指向同一个地方那个?这是什么状况?
原来是由于GCC自带的右值语义!
也就是,编译器GCC会帮你自动优化!
那么微软的编译器呢?
也会优化!
不信请看下面例子!咱们利用C++11的delete特性!
//修改源pi
a.pi=nullptr;
a.data=0;
}*/
A(A &&a)=delete;
A operator+(const A &a){
A temp(data+a.data);
cout<<endl<<"operator+ called!show temp!"<<endl;
temp.show();
cout<<endl;
return temp;
}
void show()const{
cout<<"pi="<<pi<<" data="<<data<<endl;
}
};
int main(){
int i=99;
A a(10);
a.show();
A b(i);
b.show();
A c(b);
c.show();
A d(b+c);
cout<<"show d!"<<endl;
d.show();
}
也就是说,在return temp;这一句上将要调用A(A&&)这个构造函数;
可是如今这个函数被咱们显式删除了!
b+c也是一个右值!也是须要调用移动构造函数的!
所以上一个例子其实是调用了移动语义的构造函数!
那么vs2013呢?有intelisense,你根本没法编译!!
=================================================================================