麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

C++11 智能指針

2019-11-14 12:51:05
字體:
來源:轉載
供稿:網友
 

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

標簽: c++11c++C語言對象2016-01-07 17:00 1531人閱讀 評論(0) 收藏 舉報 分類:

目錄(?)[+]

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

 簡斷截說:c++的入門坑點大家都是有目共睹的,無非就是指針的理解不深導致一些野指針,內存泄露等問題,所以就不贅述。智能指針正好能夠彌補這些問題,因為它本質是存放在棧的模板對象,只是在棧內部包了一層指針。而棧在其生命周期結束時,其中的指針指向的堆內存也自然被釋放了。因而實現了智能管理的效果,不需要考慮內存問題了,其實有點類似某種單例寫法,程序運行結束,也不用考慮單例對象內存問題。

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

     頭文件:#include <memory>

1.auto_ptr

      auto_ptr是我第一個看的智能指針,也是標準庫里的智能指針,有許多缺陷。

首先看下結構:

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

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

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

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

1、base1.get():返回當前指針對象;

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

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

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

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

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

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

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

2.unique_ptr

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

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

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

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

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

1、左值與右值:

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

2、move和forward:

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

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

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

回到這張圖,這兩個函數體也就很明朗了——重載move版本的拷貝構造函數以及重載move版本的等號賦值函數。

意思就是:把右值的對象(right)移動給左值(_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  其它的成員函數就不一一贅述,和auto_ptr大致上是相同的。總結,某種程度來說比auto_ptr更為安全,適用部分特殊情況。

3.shared_ptr

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

前兩者控制權唯一,切換的時候把前面的清除。而shared_ptr不會,照例看下底層:

很顯然,可以直接賦值和調用拷貝構造函數,且不會清空原本的智能指針。用法就很簡單了:

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

有個地方需要注意,當刪除一個智能指針時,并不影響其它兩個智能指針的繼續使用。因為該片內存添加了一個引用計數,每shared_ptr一次,引用計數+1;每次調用析構函數,引用計數減一。直到最后一個智能指針刪除,才會釋放內存。

注意:1、在繼續查看時,你會發現以下兩個函數:

其實就是和unique_ptr一樣可以通過move來切換控制權,這個時候是切換,不是共享了。

2、接下來繼續翻看,還有兩個函數:

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

用法如下:

[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、他不像其余三種,可以通過構造函數直接分配對象內存;他必須通過shared_ptr來共享內存。

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

3、不主動參與引用計數,即,share_ptr釋放了,那么weak_ptr所存的對象也釋放了。

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

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

也就是讓weak_ptr觀測shared_ptr智能指針,并且在需要時候通過lock函數返回一個shared_ptr。

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 色中色在线播放 | 成人黄视频在线观看 | 久久国产成人精品国产成人亚洲 | 国产一精品一av一免费爽爽 | 精品久久久久久久久久久下田 | 中文字幕在线观看视频一区 | 国产午夜亚洲精品午夜鲁丝片 | 欧美日韩在线视频一区 | 国产亚洲精品成人 | 日美av在线 | 美女网站黄在线观看 | 手机国产乱子伦精品视频 | 免费观看视频在线 | 成人黄色小视频在线观看 | 国产精品av久久久久久久久久 | 毛片成人网 | 黄色的视频免费观看 | 国产亚洲精品久久久久久久 | 九九视频精品在线观看 | 日韩电影av在线 | 久久久久国产成人精品亚洲午夜 | h视频在线播放 | av日韩在线免费观看 | 一级毛片在线免费观看 | 中文在线日韩 | 久久影院一区二区三区 | 国产精品一区在线看 | 欧美成人免费在线视频 | 国产精品视频一区二区三区四 | 九色成人在线 | 亚洲一区在线免费视频 | 性爱免费在线视频 | 成年免费网站 | 男女一边摸一边做羞羞视频免费 | 久久久久亚洲精品国产 | 久久精品女人天堂av | 久久国产精品二国产精品中国洋人 | 欧美一区二区网站 | 亚洲第一色婷婷 | 久久一区国产 | 99视频在线观看视频 |