c++之移動構(gòu)造函數(shù)或者移動賦值運算符的作用詳解
原理介紹
前面的文章中有的涉及到了移動構(gòu)造函數(shù)或者移動賦值運算符,對于它們的形式有了一定的了解,但是對他們的核心作用以及為什么要引入這兩個東東,很多朋友還是一知半解。本文就是來解決這個問題的。
要理解這個問題繞不開右值引用,c++11之前的 版本中只有拷貝構(gòu)造函數(shù),而拷貝構(gòu)造函數(shù)是一般會深拷貝,即會創(chuàng)建兩個完全一樣的對象,包括指針指向的區(qū)域都會進行重新申請內(nèi)存和拷貝。這種情況下如果對象是一個大數(shù)組或占用資源多的對象,就會產(chǎn)生很大的內(nèi)存拷貝開銷。那么如何解決這個問題呢?
c+11版本引入了右值引用、移動語義來解決這個問題。這里先說結(jié)論:通過移動構(gòu)造函數(shù)或移動賦值運算符產(chǎn)生的對象與元對象會產(chǎn)生一個資源的轉(zhuǎn)移。舉個形象的例子:小明手里有個籃球,小王手里沒有籃球,以前的拷貝構(gòu)造函數(shù)或者拷貝賦值運算符重載的結(jié)果是小王會按照小明手里的籃球重新買一個;而移動構(gòu)造函數(shù)和移動賦值運算符重載實現(xiàn)則更像是小王把小明手里的籃球放到自己手里,而小明手里沒有了籃球。
從上面的例子可以看出移動構(gòu)造函數(shù)或移動賦值運算符的作用就是通過資源管理權(quán)轉(zhuǎn)移的方式實現(xiàn)對象的構(gòu)造,使得可以減少內(nèi)存拷貝的開銷。
移動構(gòu)造函數(shù)的的參數(shù)一定是一個右值引用。
下面是一個給出一個移動構(gòu)造函數(shù)的典型的例子:
class MyClass { std::string str; //一個類成員 int* ptr; //一個指針成員 public: A(){} A(MyClass && a)::str(std::move(a.str)) { } A operator=(MyClass&& a) //移動賦值運算符重載 { if(this != &a) { str = std:move(a.str); //這里因為str::string類已經(jīng)實現(xiàn)了移動構(gòu)造賦值運算符,std::string作為一個類已經(jīng)支持了這個,所以可以這樣做,如果是 ptr = a.ptr; //需要自己去切換指針所指向的區(qū)域 a.ptr = nullptr; } } }
注意事項
- 一個類的移動構(gòu)造函數(shù)或移動賦值運算符的實現(xiàn)是由類自己實現(xiàn)的
- 如果要使用移動構(gòu)造函數(shù)或者移動賦值運算符,那么用戶必須顯式的定義移動構(gòu)造函數(shù)和移動賦值運算符的重載
- 一些c++標準庫中提供的類很多都已經(jīng)實現(xiàn)了移動構(gòu)造函數(shù)和移動賦值運算符的重載,例如std::string、stl容器類、智能指針(std::shared_ptr<T>、std::unique_ptr<T>)等
- 用戶自己定義類在有需要的情況下需要在自定義的類中實現(xiàn)移動構(gòu)造函數(shù)和移動賦值運算符重載。
- 移動構(gòu)造函數(shù)或移動賦值運算符重載實現(xiàn)基于右值引用,一定是以右值引用作為參數(shù)的
思考
移動構(gòu)造函數(shù)本質(zhì)是資源管理權(quán)的轉(zhuǎn)移,那如果跟std::shared_ptr<T>會發(fā)生什么?
- 請看下面的代碼:
class MyClass { public: A(){ std::cout<<"A的構(gòu)造函數(shù)"<<std::endl; } ~A(){ std::cout<<"A的析構(gòu)函數(shù)"<<std::endl; } } class Container { private: std::shared_ptr<MyClass> ptr; public: Container(Container&& container):ptr(std::move(container.ptr)) { std::cout<<"移動構(gòu)造函數(shù)"<<std::endl; } Container operator=(Container&& container) { if(this != &container) //這里不能少 { ptr = std::move(container.ptr); //這里也可以,因為std::shared_ptr內(nèi)部實習(xí)拿了移動賦值運算符 } } }
shared_ptr 的移動操作:
- 轉(zhuǎn)移資源所有權(quán)
- 源指針置空
- 保持引用計數(shù)不變
- 是線程安全和異常安全的
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于C++中構(gòu)造函數(shù)初始化成員列表的總結(jié)
下面小編就為大家?guī)硪黄P(guān)于C++中構(gòu)造函數(shù)初始化成員列表的總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12