C++ 標準庫智能指標

來源:互聯網
上載者:User

標籤:類型   引用計數   直接   ack   自己的   ase   而不是   fir   get   

  整理一下c++中shared_ptr,weak_ptr,unique_ptr三種指標的使用案例和注意事項,讓程式資源更加案例,在標準庫中,需要包含<memory>,在boost庫中,

  一. 智能指標unique_ptr

    與shared_ptr相似,區別在於unique_ptr是獨立擁有對象權,因此只有move語言,無拷貝語義,不做其它詳述了。

  二.智能指標share_ptr

  1.基本使用

class Sam{public:    Sam(int v):val(v) {    }    int32_t val;

    ~Sam()
    {
      std::cout << "~sam()" << std::endl;
    }

};

//definestd::shared_ptr<Sam> p1(new Sam(100));std::shared_ptr<Sam> p2 = std::make_shared<Sam>(200);
p1.reset(new Sam(300));  //new first, delete second
std::shared_ptr<Sam> p3 = p1;

//get the base ptr
Sam* pSam = p1.get();

//modify
(*p1).val = 10000;

//cal is 1
bool b = p1.unique();

p1.reset();

 

  2.進階使用

  (1)使用shared_ptr<list<T>>類型,調用reset的時候list中的所有的Sam對象都會調用解構函式

std::shared_ptr<std::list<Sam>> lst_ptr( new std::list<Sam>(8, 33));std::cout << lst_ptr.get()->size() << std::endl;lst_ptr.reset();

  (2)程式不知道自己需要使用多少對象. 且程式需要在多個對象間共用資料,使用vector<shared_ptr<T>>類型:

std::vector<std::shared_ptr<Sam>> vec_ptr;std::shared_ptr<Sam> p1(new Sam(10));vec_ptr.push_back(p1);

  (3)定製自己的刪除器:在shared_ptr釋放時會自動調用 函數刪除器而不是預設的解構函式了:

void Deleter(Sam* obj) {    std::cout << "Deleter" << std::endl;}

std::shared_ptr<Sam> sp(new Sam(10), Deleter);

  如果將刪除器定義成類,則自由性更大,下面的代碼執行後會調用解構函式(簡單地使用了delete)

template<typename T>class Deleter{public:    void operator () (T* x) const    {        if (x != NULL)        {            std::cout << __LINE__ << std::endl;            delete x;            x = NULL;        }    }};

std::shared_ptr<Sam> sp(new Sam(10), Deleter<Sam> {})

 

  3.錯誤用法

  情形一:一個指標同時放入兩個shared_ptr,會在第二個shared_ptr釋放時引發異常。

pSam = new Sam(400);std::shared_ptr<Sam> p4(pSam);std::shared_ptr<Sam> p5(pSam);

  情形二:資料結構形成環的時候,shared_ptr不能正常工作,需要與weak_ptr協作解決此問題,用例如下:

class CB;class CA;class CA{public:    CA() {}    ~CA() { std::cout << "~CA()" << std::endl; }    void Register(const std::shared_ptr<CB>& sp)    {        m_sp = sp;    }private:    std::shared_ptr<CB> m_sp;};class CB{public:    CB() {};    ~CB() { std::cout << "~CB()" << std::endl; };    void Register(const std::shared_ptr<CA>& sp)    {        m_sp = sp;    }private:    std::shared_ptr<CA> m_sp;};  std::shared_ptr<CA> spa(new CA);    std::shared_ptr<CB> spb(new CB);    spb->Register(spa);    spa->Register(spb);    printf("%d\n", spb.use_count()); // 2    printf("%d\n", spa.use_count()); // 2

  程式結束後,無法釋放記憶體,也沒有調用解構函式,智能指標的引用計數都是2,這就是循環參考問題。

  情形三:普通類繼承 enable_shared_from_this 的錯誤情況:

  

class Y : public std::enable_shared_from_this<Y>            {            public:                std::shared_ptr<Y> GetSharePtr()                {                    return shared_from_this();                }            };


    Y y;
    std::shared_ptr<Y> spy = y.GetSharePtr(); // 錯誤, y 根本不是 new 建立的
    Y* y = new Y;
    std::shared_ptr<Y> spy = y->GetSharePtr(); // 錯誤, 問題依舊存在, 程式直接崩潰

    std::shared_ptr<Y> spy(new Y);
    std::shared_ptr<Y> p = spy->GetSharePtr();
    printf("%d\n", p.use_count()); // 2

  前兩者錯誤是因為雖然Y由 enable_shared_from_this派生,但智能指標的資料結構並沒有因為new Y的操作賦值 。

  

  三. 智能指標weak_ptr

  構造和析構不會引起引用計數的增加或減少。沒有重載 * 和 -> 但可以使用lock獲得一個可用的shared_ptr對象,且在所指對象記憶體已經無效時,返回指標空值nullptr.

  帶有的成員函數reset,use_count

std::shared_ptr<Sam> sam_ptr(new Sam(6));    std::weak_ptr<Sam> sam_wk = sam_ptr;    std::shared_ptr<Sam> sp = sam_wk.lock();    if (sp)    {        std::cout << (*sp).val << endl;  // 6    }    std::cout << sp.use_count() << std::endl;  //2

 

  

C++ 標準庫智能指標

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.