国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

C++11 智能指針

2019-11-14 12:52:29
字體:
供稿:網(wǎng)友
 

[置頂] c++11智能指針解析——揭開底層面紗,完整理解智能指針

標(biāo)簽: c++11c++C語言對(duì)象2016-01-07 17:00 1531人閱讀 評(píng)論(0) 收藏 舉報(bào) 分類:

目錄(?)[+]

昨天跟同事小小的研究了下關(guān)于不同平臺(tái)下的字節(jié)對(duì)齊問題,起因是遇到了一個(gè)坑,vs上沒有問題,在安卓上卻崩潰了。找了半天后發(fā)現(xiàn)是c++字節(jié)補(bǔ)齊問題,期間包括使用#PRagma pack(1)來限定字節(jié)對(duì)齊方式等各種條件,也是把我們搞的七暈八素,總算是進(jìn)一步了解了c++對(duì)象結(jié)構(gòu)以及編譯器的操作(有機(jī)會(huì)的話也補(bǔ)充下字節(jié)對(duì)齊的理解)。進(jìn)而想到了智能指針,稍微了解下。第一次接觸智能指針,天知道大學(xué)期間自己有多不努力,很多知識(shí)點(diǎn)都得留到現(xiàn)在來補(bǔ)齊,所以還是做做筆記吧。

 簡(jiǎn)斷截說:c++的入門坑點(diǎn)大家都是有目共睹的,無非就是指針的理解不深導(dǎo)致一些野指針,內(nèi)存泄露等問題,所以就不贅述。智能指針正好能夠彌補(bǔ)這些問題,因?yàn)樗举|(zhì)是存放在棧的模板對(duì)象,只是在棧內(nèi)部包了一層指針。而棧在其生命周期結(jié)束時(shí),其中的指針指向的堆內(nèi)存也自然被釋放了。因而實(shí)現(xiàn)了智能管理的效果,不需要考慮內(nèi)存問題了,其實(shí)有點(diǎn)類似某種單例寫法,程序運(yùn)行結(jié)束,也不用考慮單例對(duì)象內(nèi)存問題。

     本次討論:C++11之前的auto_ptr; c++11新加的unique_ptr, shared_ptr以及weak_ptr。

     頭文件:#include <memory>

1.auto_ptr

      auto_ptr是我第一個(gè)看的智能指針,也是標(biāo)準(zhǔn)庫里的智能指針,有許多缺陷。

首先看下結(jié)構(gòu):

從圖中可以看書也是一個(gè)模板,使用方法大致類似于vector模板。如下:

[cpp] view plain copy 在CODE上查看代碼片class Base1  {      //__int64 ss;  //public:      bool dd;      int m_itest;  public:      virtual void func(){          cout << "test successed" << endl;      }  };//先寫一個(gè)測(cè)試類  main函數(shù)如下:

[cpp] view%20plain copy int _tmain(int argc, _TCHAR* argv[])  {      auto_ptr <Base1> base1(new Base1);//可理解為先聲明一個(gè)名為base1的Base1類型智能指針,然后再base1里面管理new Base1          if (base1.get())//get是智能指針的函數(shù),返回當(dāng)前當(dāng)前智能指針對(duì)象,即用以判斷是否為空          {           base1->func();            }          return 0;  }  正常用法是這樣,然而我們可以再仔細(xì)翻看下底層:

從上圖可以看出,該智能指針成員函數(shù)也與vector相似,很容易得出

1、base1.get():返回當(dāng)前指針對(duì)象;

2、base1.release():清空當(dāng)前智能指針對(duì)象,并返回類型指針。所以假如我們要正常刪除,那么需要這樣:

[cpp] view plain copy 在CODE上查看代碼片Base1*base2 = base1.release();  delete base2;  很麻煩對(duì)不對(duì),沒關(guān)系,還有第三個(gè)函數(shù)呢

3、base1.reset():從圖中可看出,是重置智能指針,即把內(nèi)存刪除,且智能指針指向空,但類型不變,所以可以這樣安全便捷地刪除:

[cpp] view%20plain copy base1.reset();  

然而繼續(xù)看,還有一個(gè)問題:auto_ptr還重載了等號(hào)操作符,由圖可知意思是把賦值智能指針的內(nèi)存交給被賦值智能指針,即如下意思:

[cpp] view plain copy 在CODE上查看代碼片auto_ptr <Base1> base2;  base2 = base1;//將base1的控制權(quán)轉(zhuǎn)交給base2,且base1清空了  base2->func();  因此這樣就有些問題,控制權(quán)可以隨便轉(zhuǎn)換,但是只有一個(gè)在用,用起來會(huì)受到諸多限制,所以有了下面的智能指針。

介紹之前先上一張別人的表格,來源:http://my.oschina.net/hevakelcj/blog/465978,這是c++11中的智能指針與boost庫中的比較,原本boost就是為完善auto_ptr搞得這些,現(xiàn)在c++11有了,也就不需要再用咯。

2.unique_ptr

 C++11引入了許多便捷的功能,其中也包括這個(gè),在用之前我們可以先看下底層:

可以清楚的看到,unique_ptr中的拷貝構(gòu)造和賦值操作符delete了,所以也就意味著,他和auto_ptr有區(qū)別,控制權(quán)唯一,不能隨意轉(zhuǎn)換。用法都差不多:

[cpp] view plain copy 在CODE上查看代碼片unique_ptr<Base1> base1(new Base1);  unique_ptr<Base1> base2;//但是不能用拷貝構(gòu)造和等號(hào)賦值把base1賦值給base2了  但是如果想切換控制權(quán)的話也不是沒有辦法,我們可以看到還有個(gè)這樣的函數(shù)

要理解這兩個(gè)函數(shù),首先要理解c++11引入的move和forward;而要理解move和forward得先理解左值和右值概念。所以還是講全一點(diǎn)吧(已經(jīng)了解的就直接跳過可以):

補(bǔ)充知識(shí)點(diǎn)(其實(shí)可以直接看我下一篇更方便理解:點(diǎn)擊打開鏈接):

1、左值與右值:

       左值指的是既能夠出現(xiàn)在等號(hào)左邊也能出現(xiàn)在等號(hào)右邊的變量(或表達(dá)式),右值指的則是只能出現(xiàn)在等號(hào)右邊的變量(或表達(dá)式)。需要注意的是,左值是指表達(dá)式結(jié)束后依然存在的持久對(duì)象,而右值是指表達(dá)式結(jié)束時(shí)就不再存在的臨時(shí)對(duì)象。T& 指向的是 lvalue,而 const T& 指向的,卻可能是 lvalue 或 rvalue,左值引用&與右值引用&&(右值引用是c++11加上的)。

2、move和forward:

       需要明確的是,move函數(shù)可以是用于構(gòu)造函數(shù),也可以用于賦值函數(shù),但都需要手動(dòng)顯示添加。其實(shí)move函數(shù)用直白點(diǎn)的話來說就是省去拷貝構(gòu)造和賦值時(shí)中間的臨時(shí)對(duì)象,將資源的內(nèi)存從一個(gè)對(duì)象移動(dòng)到(共享也可以)另一個(gè)對(duì)象。官話是:c++11 中的 move() 是這樣一個(gè)函數(shù),它接受一個(gè)參數(shù),然后返回一個(gè)該參數(shù)對(duì)應(yīng)的右值引用。

       std::forward<T>(u) 有兩個(gè)參數(shù):T 與 u。當(dāng)T為左值引用類型時(shí),u將被轉(zhuǎn)換為T類型的左值,否則u將被轉(zhuǎn)換為T類型右值。如此定義std::forward是為了在使用右值引用參數(shù)的函數(shù)模板中解決參數(shù)的完美轉(zhuǎn)發(fā)問題。

其實(shí)這里說的不夠清晰,下次翻譯一篇國外的解釋,閱讀下來就能很好理解move這個(gè)概念了,這里先不深入。

回到這張圖,這兩個(gè)函數(shù)體也就很明朗了——重載move版本的拷貝構(gòu)造函數(shù)以及重載move版本的等號(hào)賦值函數(shù)。

意思就是:把右值的對(duì)象(right)移動(dòng)給左值(_myt&),并且右值清空。

那么用法來了:

[cpp] view plain copy 在CODE上查看代碼片unique_ptr<Base1> base1(new Base1);  unique_ptr<Base1> base2=move(base1);//base1變成empty  unique_ptr<Base1> base3;  base3 = move(base2);//base2變成empty  其它的成員函數(shù)就不一一贅述,和auto_ptr大致上是相同的。總結(jié),某種程度來說比auto_ptr更為安全,適用部分特殊情況。

3.shared_ptr

如果完全理解了上面兩個(gè)ptr的底層,那么shared_ptr的也就容易理解多了。但是和前兩者有很大區(qū)別——

前兩者控制權(quán)唯一,切換的時(shí)候把前面的清除。而shared_ptr不會(huì),照例看下底層:

很顯然,可以直接賦值和調(diào)用拷貝構(gòu)造函數(shù),且不會(huì)清空原本的智能指針。用法就很簡(jiǎn)單了:

[cpp] view plain copy 在CODE上查看代碼片shared_ptr<Base1> base1(new Base1);  shared_ptr<Base1> base2=base1;  shared_ptr<Base1> base3;  base3 = base2;//三個(gè)共享一個(gè)  

有個(gè)地方需要注意,當(dāng)刪除一個(gè)智能指針時(shí),并不影響其它兩個(gè)智能指針的繼續(xù)使用。因?yàn)樵撈瑑?nèi)存添加了一個(gè)引用計(jì)數(shù),每shared_ptr一次,引用計(jì)數(shù)+1;每次調(diào)用析構(gòu)函數(shù),引用計(jì)數(shù)減一。直到最后一個(gè)智能指針刪除,才會(huì)釋放內(nèi)存。

注意:1、在繼續(xù)查看時(shí),你會(huì)發(fā)現(xiàn)以下兩個(gè)函數(shù):

其實(shí)就是和unique_ptr一樣可以通過move來切換控制權(quán),這個(gè)時(shí)候是切換,不是共享了。

2、接下來繼續(xù)翻看,還有兩個(gè)函數(shù):

(其實(shí)auto_ptr也有,只是一樣,沒必要截圖了)也就是說,auto_ptr和unique_ptr都可以通過move函數(shù)轉(zhuǎn)換成shared_ptr類型,當(dāng)然,一樣是切換控制權(quán)的形式,即舊的置空。

用法如下:

[cpp] view plain copy 在CODE上查看代碼片auto_ptr<Base1>   base1(new Base1);  shared_ptr<Base1> base2=move(base1);  4.weak_ptrred_ptr

weak_ptr更像是shared_ptr的助手:

1、他不像其余三種,可以通過構(gòu)造函數(shù)直接分配對(duì)象內(nèi)存;他必須通過shared_ptr來共享內(nèi)存。

2、沒有重載opreator*和->操作符,也就意味著即使分配到對(duì)象,他也沒法使用該對(duì)象

3、不主動(dòng)參與引用計(jì)數(shù),即,share_ptr釋放了,那么weak_ptr所存的對(duì)象也釋放了。

4、使用成員函數(shù)use_count()可以查看當(dāng)前引用計(jì)數(shù),expired()判斷引用計(jì)數(shù)是否為空。

5、lock()函數(shù),返回一個(gè)shared_ptr智能指針:

也就是讓weak_ptr觀測(cè)shared_ptr智能指針,并且在需要時(shí)候通過lock函數(shù)返回一個(gè)shared_ptr。

6、此外,百科上說:助手類enable_shared_from_this的Shared_from_this會(huì)返回this的shared_ptr,所以只需讓要被shared_ptr管理的類繼承它即可。我倒是沒試,有興趣的可以試試,大致意思也就是這般。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 兰西县| 木兰县| 保靖县| 道真| 临澧县| 龙胜| 平塘县| 通城县| 乳山市| 嵊泗县| 宽甸| 鄢陵县| 宁河县| 玛多县| 昆山市| 三亚市| 盐池县| 镇坪县| 油尖旺区| 资溪县| 屯昌县| 临沂市| 宣恩县| 平塘县| 广饶县| 天台县| 高清| 肇庆市| 富锦市| 长阳| 界首市| 孟村| 新巴尔虎左旗| 永丰县| 黄陵县| 睢宁县| 仪征市| 诏安县| 天柱县| 双城市| 集安市|