<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          智能指針常見錯(cuò)誤用法

          共 4774字,需瀏覽 10分鐘

           ·

          2020-12-07 09:23

          前言

          智能指針的出現(xiàn)大大減輕了 C++ 程序員的心理負(fù)擔(dān)(最少對(duì)于我是這樣的),不用再時(shí)時(shí)刻刻擔(dān)心一個(gè) new 出來的指針是否被 delete 的問題了。雖然智能指針很強(qiáng)大,但是如果用不好,還是會(huì)導(dǎo)致各種各樣的問題。最近,在項(xiàng)目里看到了幾種智能指針的典型錯(cuò)誤用法。有的嚴(yán)重,有的輕,有的問題在研發(fā)階段并沒有立刻暴露出來,埋下了一顆定時(shí)炸彈。趁著這個(gè)機(jī)會(huì),總結(jié)一下幾種常見的錯(cuò)誤用法。希望對(duì)各位小伙伴兒有幫助。

          說明:智能指針有很多種,標(biāo)準(zhǔn)庫(kù)提供了幾種,比如最常用的 shared_ptrunique_ptr, 比較少用的 weak_ptr 以及被廢棄的 auto_ptr。項(xiàng)目代碼里還有一種基于引用計(jì)數(shù)的智能指針。本文只列舉幾種常見的錯(cuò)誤用法,不會(huì)深入到各種智能指針的實(shí)現(xiàn)。如果想深刻理解智能指針的用法,一定要看源碼。

          錯(cuò)誤用法

          在列舉各種錯(cuò)誤用法之前,想說明一點(diǎn):這些錯(cuò)誤都是實(shí)際遇到過的,并不是憑空想出來的。所以,即使有些示例代碼錯(cuò)的是那么明顯,也請(qǐng)不要輕視。

          1. 同一指針交給兩個(gè)智能指針管理導(dǎo)致二次釋放

          namespace?case1
          {
          ????/*
          ????*?pRawData?is?already?managed?by?a?shared_ptr?(pData?in?function?#Entry()),
          ????*?in?function?#Use(),?another?shared_ptr?(pNewData)?manages?the?raw?pointer?too.
          ????*?now,?we?have?two?shared_ptr?manage?the?same?raw?pointer.?Oops,?double?free!
          ????*/

          ????static?void?Use(Common::CDerived*?pRawData)
          ????
          {
          ????????std::shared_ptr?pNewData(pRawData);
          ????????pNewData->DoSomething();
          ????}

          ????static?void?Entry()
          ????
          {
          ????????auto?pData?=?std::make_shared();
          ????????Use(pData.get());
          ????}
          }

          2. 錯(cuò)誤的動(dòng)態(tài)轉(zhuǎn)換導(dǎo)致的二次釋放

          #pragma?once
          #include?

          #include?"common.h"

          namespace?case2
          {
          ????static?void?Use(std::shared_ptr?pData)
          ????
          {
          ????????pData->DoSomething();
          ????}

          ????static?std::shared_ptr?GetData()
          ????
          {
          ????????return?std::make_shared();
          ????}
          ????static?void?Entry()
          ????
          {
          ????????auto?pTest?=?std::make_shared();

          ????????//?Oops,?double?free
          ????????std::shared_ptr?pData?=?GetData();
          ????????auto?pRawData?=?pData.get();
          ????????Common::CDerived*?pDerived?=?dynamic_cast(pRawData);
          ????????if?(pDerived)
          ????????{
          ????????????Use(std::shared_ptr(pDerived));
          ????????}

          ????????//?code?below?is?good
          ????????//Use(std::dynamic_pointer_cast(pData));
          ????}
          }

          3. 返回智能指針管理的原生指針

          namespace?case3
          {
          ????/*
          ????*?after?#ReturnRawPointer()?and?#GetRawPointer()?returned,?shared_ptr's?destructor?is?called,
          ????*?then?the?returned?raw?pointer?points?to?a?deleted?address.?bang!
          ????*/

          ????static?Common::CDerived*?ReturnRawPointer()
          ????
          {
          ????????auto?pData?=?std::make_shared();
          ????????return?pData.get();
          ????}

          ????static?bool?GetRawPointer(Common::CDerived*?&?pReturnedData)
          ????
          {
          ????????auto?pData?=?std::make_shared();
          ????????pReturnedData?=?pData.get();
          ????????return?(pReturnedData?!=?nullptr);
          ????}

          ????static?void?Entry()
          ????
          {
          ????????auto?pData?=?ReturnRawPointer();
          ????????pData->DoSomething();

          ????????pData?=?nullptr;
          ????????GetRawPointer(pData);
          ????????pData->DoSomething();
          ????}
          }

          4. 類中的成員變量指針交給外部智能指針管理

          namespace?case4
          {
          ????/*
          ????*?CTest::pData?is?managed?by?CTest,?but?when?call?#Use(),?it?is?used?to?construct?a?shared_pt,
          ????*?then?it?is?also?managed?by?a?shared_ptr.?double?free!
          ????*/

          ????class?CTest
          ????{

          ????public:
          ????????CTest()?{?pData?=?new?Common::CDerived();?}

          ????????~CTest()?{?delete?pData;?}

          ????????Common::CDerived*?pData;
          ????};

          ????/*?this?function?need?a?shared_ptr,?this?is?ok.*/
          ????static?void?Use(std::shared_ptr?pData)
          ????
          {
          ????????pData->DoSomething();
          ????}

          ????static?void?Entry()
          ????
          {
          ????????auto?pTest?=?std::make_shared();
          ????????Use(std::shared_ptr(pTest->pData));
          ????}
          }

          5. 棧變量的地址交給智能指針管理

          namespace?case5
          {
          ????/*
          ????*?data?is?on?stack,?after?managed?by?a?shared_ptr,?it?will?be?deleted.
          ????*?we?CAN?NOT?delete?an?address?on?stack!
          ????*/

          ????static?void?Use(std::shared_ptr?pData)
          ????
          {
          ????????pData->DoSomething();
          ????}

          ????static?void?Entry()
          ????
          {
          ????????//?well,?I?have?simplify?this?error?quite?much.
          ????????Common::CDerived?data;
          ????????auto?pData?=?std::shared_ptr(&data);

          ????????Use(pData);
          ????}
          }

          6. 循環(huán)引用導(dǎo)致的內(nèi)存泄漏

          #pragma?once
          #include?
          #include?
          #include?"common.h"

          namespace?case6
          {
          ????class?CPerson
          ????{

          ????public:
          ????????CPerson()?{?printf(__FUNCTION__?"\n");?}
          ????????virtual?~CPerson()?{?printf(__FUNCTION__?"\n");?}
          ????};

          ????class?CParent?:?public?CPerson
          ????{
          ????public:
          ????????CParent()?{?printf(__FUNCTION__?"\n");?}
          ????????virtual?~CParent()?{?printf(__FUNCTION__?"\n");?}
          ????????std::vector<std::shared_ptr>?children;
          ????};

          ????class?CChild?:?public?CPerson
          ????{
          ????public:
          ????????CChild()?{?printf(__FUNCTION__?"\n");?}
          ????????virtual?~CChild()?{?printf(__FUNCTION__?"\n");?}
          ????????std::shared_ptr?parent;
          ????};

          ????static?void?Entry()
          ????
          {
          ????????//?Oops,?no?one?will?be?died?then.
          ????????std::shared_ptr?parent?=?std::make_shared();
          ????????std::shared_ptr?child1?=?std::make_shared();
          ????????std::shared_ptr?child2?=?std::make_shared();
          ????????std::shared_ptr?child3?=?std::make_shared();

          ????????parent->children.push_back(child1);
          ????????parent->children.push_back(child2);
          ????????parent->children.push_back(child3);
          ????????child1->parent?=?parent;
          ????????child2->parent?=?parent;
          ????????child3->parent?=?parent;
          ????}
          }

          示例代碼

          完整的示例代碼下載地址

          CSDN:https://download.csdn.net/download/xiaoyanilw/13203123

          百度云:https://pan.baidu.com/s/1dFUKevDXJZfja3HyO-jazg 提取碼: 8ra8

          總結(jié)

          以上示例代碼雖然有的看起來非常不可思議,這是我簡(jiǎn)化后的結(jié)果,在實(shí)際代碼中經(jīng)常以另外一種形式出現(xiàn),一不小心就容易中招。


          瀏覽 72
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧洲亚洲视频在线 | 99操B视频 | 囯产精品久久久久久久久久98 | 性爱免费视频网站 | 成人免费黄片 |