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,你根本沒法編譯!!
=================================================================================