欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++智能指針讀書筆記

 更新時(shí)間:2015年11月24日 08:59:13   投稿:hebedich  
本篇隨筆僅作為個(gè)人學(xué)習(xí)《C++ Primer》智能指針一節(jié)后的部分小結(jié),抄書嚴(yán)重,伴隨個(gè)人理解。主要介紹shared_ptr、make_shared、weak_ptr的用法和聯(lián)系

最近在補(bǔ)看《C++ Primer Plus》第六版,這的確是本好書,其中關(guān)于智能指針的章節(jié)解析的非常清晰,一解我以前的多處困惑。C++面試過程中,很多面試官都喜歡問智能指針相關(guān)的問題,比如你知道哪些智能指針?shared_ptr的設(shè)計(jì)原理是什么?如果讓你自己設(shè)計(jì)一個(gè)智能指針,你如何完成?等等……。而且在看開源的C++項(xiàng)目時(shí),也能隨處看到智能指針的影子。這說明智能指針不僅是面試官愛問的題材,更是非常有實(shí)用價(jià)值。

C++通過一對運(yùn)算符 new 和 delete 進(jìn)行動(dòng)態(tài)內(nèi)存管理,new在動(dòng)態(tài)內(nèi)存中為對象分配空間并返回一個(gè)指向該對象的指針,delete接受一個(gè)動(dòng)態(tài)對象的指針,銷毀對象并釋放與之相關(guān)的內(nèi)存。然而這樣的動(dòng)態(tài)內(nèi)存的使用很危險(xiǎn),因?yàn)闊o法確保始終能在合適的時(shí)間釋放內(nèi)存對象。如果忘記釋放內(nèi)存,可能造成內(nèi)存泄露;如果在尚有指針引用內(nèi)存的情況下釋放內(nèi)存,會(huì)產(chǎn)生非法訪問內(nèi)存的指針。

C++11中,新的標(biāo)準(zhǔn)庫提供了兩種智能指針(smart pointer)類型來更安全地管理對象。智能指針的使用和常規(guī)指針類似,只是它們多了自動(dòng)釋放所指向的對象的功能。兩種指針的區(qū)別在于管理底層指針的方式:shared_ptr允許多個(gè)指針指向同一個(gè)對象,unique_ptr不支持。標(biāo)準(zhǔn)庫還提供了weak_ptr這一弱指針,指向shared_ptr所管理的對象。三種類型都定義在頭文件memory中。

shared_ptr的使用和vector很相似,在尖括號(hào)內(nèi)說明所指向?qū)ο蟮念愋停?/p>

復(fù)制代碼 代碼如下:
shared_ptr<string> p1              // p1是shared_ptr,指向string類型
shared_ptr<list<int>> p2     // p2是shared_ptr,指向list的int

解引用一個(gè)智能指針就能獲得它所指向的對象,在if語句中使用智能指針可以判斷它指向的對象是否為空:

復(fù)制代碼 代碼如下:
// 如果p1非空,檢查p1是否指向一個(gè)空的string對象
if (p1 && p1->empty())
    *p1 = "creat";        // 如果p1非空且指向一個(gè)空的string對象,解引用p1,為其賦新值creat

最安全的分配和使用shared_ptr的方法是調(diào)用名為make_shared這一標(biāo)準(zhǔn)庫函數(shù)。此函數(shù)在動(dòng)態(tài)內(nèi)存中分配并初始化它,返回指向此對象的shared_ptr。該函數(shù)定義在memory中。

make_shared的定義和shared_ptr相似,必須制定要?jiǎng)?chuàng)建對象的類型,如:

// 指向一個(gè)值為1的int的shared_ptr
shared_ptr<int> p3 = make_shared<int>)(1);
// 指向一個(gè)值為“www”的string的shared_ptr
shared_ptr<string> p4 = make_shared<string>(3, "w");
// 指向一個(gè)初始化的int,值為0
shared_ptr<int> p5 = make_shared<int>)();

也可以使用auto定義對象保存make_shared,可以省去書寫shared_ptr的麻煩。

  shared——ptr中有一個(gè)關(guān)聯(lián)的指示器,稱為引用計(jì)數(shù)??梢钥醋鲆粋€(gè)計(jì)數(shù)器,每當(dāng)shared_ptr對象進(jìn)行拷貝操作,如用一個(gè)shared_ptr對象初始化另一個(gè)shared_ptr對象、作為函數(shù)的實(shí)參、作為函數(shù)返回值時(shí),引用計(jì)數(shù)都會(huì)遞增(視為數(shù)值+1)。當(dāng)賦予shared_ptr新值或者shared_ptr被銷毀時(shí),引用計(jì)數(shù)遞減。當(dāng)引用計(jì)數(shù)減為0,通過析構(gòu)函數(shù),shared_ptr自動(dòng)銷毀所管理的對象,釋放內(nèi)存。

  需要注意的是,如果多個(gè)對象共享底層數(shù)據(jù),當(dāng)某一對象被銷毀,不能單方面銷毀底層數(shù)據(jù),例如:

Blob<string> b1;
{ // 新作用域
  Blob<string> b2 = { "x", "b", "b" };
  b1 = b2;
}  // 當(dāng)離開局部作用域,b2被銷毀,然而b2中的元素xbb并不會(huì)被銷毀
   // b1指向最初由b2創(chuàng)建的元素,即“x”, "b", "b",b1依舊可以它們

  weak_ptr是指向shared_ptr管理的對象的一種智能指針,然而它不控制所指向?qū)ο蟮纳嫫?。將一個(gè)weak_ptr綁定在shared_ptr上,不會(huì)改變shared_ptr的引用計(jì)數(shù),一旦最后一個(gè)shared_ptr的指向?qū)ο蟊淮蒌N毀,對象就會(huì)被釋放,有無weak_ptr并無卵影響。我的理解是,weak_ptr提供了指向shared_ptr底層數(shù)據(jù)的功能,控制了shared_ptr對底層數(shù)據(jù)的訪問。

  因?yàn)閣eak_ptr指向的對象可能不存在(shared_ptr指向的最后一個(gè)對象被銷毀時(shí)),因而用它不能直接訪問對象,必須調(diào)用lock函數(shù)檢查其指向的對象是否存在。很容易寫出一個(gè)選擇語句進(jìn)行控制:

auto bb = make_shared<string>(2, 'b');
weak_ptr<string> xbb(bb);
if (shared_pr<int> np = xbb.lock()) { // np不為空條件成立
  // 在if語句內(nèi),np和xbb共享對象  
}

補(bǔ)充weak_ptr相關(guān)的函數(shù),便于理解:

w.reset 將w置為空
w.use_count() 與w共享對象的個(gè)數(shù)
w.expired() 若w.use_count()為0,返回true,否則返回false
w.lock() 若w.expired()為true,返回一個(gè)空shared_ptr,否則返回一個(gè)指向w的對象的shared_ptr

加入《C++ Primer 5th》中的12.19題參照,題中和“智能指針和異?!辈⑽丛诒酒S筆中介紹

#include <iostream>    
#include <string>
#include <vector>
#include <memory>
#include <initializer_list>
using namespace std;
using std::string;
using std::vector;
class StrBlobPtr;
class StrBlob {
public:
  friend class StrBlobPtr;      // 友元
  StrBlobPtr begin();         // 聲明StrBlob類中的begin()和end()
  StrBlobPtr end();          // 返回一個(gè)指向它自身的StrBlobPtr
public:
  typedef vector<string>::size_type size_type;  // 類型別名,size_type = vector<string>::size_type

  StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {};  // 接受一個(gè)initializer_list參數(shù)的構(gòu)造函數(shù)將其參數(shù)傳                                                            遞給對應(yīng)的vector構(gòu)造函數(shù),通過拷貝列表
  StrBlob::StrBlob() : data(make_shared<vector<string>>()) {};                 // 構(gòu)造函數(shù),初始化data成員,指向動(dòng)態(tài)分配的vector                                                            中的值初始化vector元素
  void push_back(const string &t) { data->push_back(t); }
  string& StrBlob::front() {
    check(0, "front on empty StrBlob");
    return data->front();
  }
  string& StrBlob::back() {
    check(0, "back on empty StrBlob");
    return data->back();
  }
  void StrBlob::pop_back() {             // 刪除尾元素
    check(0, "pop_back empty StrBlob");
    return data->pop_back();
  }
  string& front() const { return data->front(); };
  string& back() const { return data->back(); };
private:
  shared_ptr<vector<string>> data;
  void StrBlob::check(size_type i, const string &msg) const {  // 檢查元素是否存在
    if (i >= data->size())                  // 若不存在
      throw out_of_range(msg);               // 拋出異常
  }
};
class StrBlobPtr {
public:
  StrBlobPtr() : curr(0) {};
  StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) {};
  string & deref() const {
    auto p = check(curr, "dereference past end");
    return (*p)[curr];  // check成功,返回一個(gè)p指針,指向make_shared指向的vector
  }            // 解引用,make_shared獲取vector,用下表運(yùn)算符返回curr位置上的對象
  StrBlobPtr& incr() {
    check(curr, "increment past end of StrBlobPtr");
    ++curr;
    return *this;
  }
  bool operator!=(const StrBlobPtr& p) { return p.curr != curr; }

private:
  weak_ptr<vector<string>> wptr;
  size_t curr;
  shared_ptr<vector<string>> check(size_t i, const string& msg) const
  {
    auto rent = wptr.lock();
    if (!rent)
      throw runtime_error("unbound StrBlobPtr");
    if (i >= rent->size())
      throw out_of_range(msg);
    return rent;
  }
};
StrBlobPtr StrBlob::begin()
{
  return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
  return StrBlobPtr(*this, data->size());
}

相關(guān)文章

  • C++ using namespace std 用法深入解析

    C++ using namespace std 用法深入解析

    以下是對C++中using namespace std的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下
    2013-07-07
  • VC判斷進(jìn)程是否具有administrator權(quán)限的方法

    VC判斷進(jìn)程是否具有administrator權(quán)限的方法

    這篇文章主要介紹了VC判斷進(jìn)程是否具有administrator權(quán)限的方法,在Windows應(yīng)用程序設(shè)計(jì)中具有一定的實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • 一文詳解matlab實(shí)現(xiàn)形態(tài)學(xué)圖像處理

    一文詳解matlab實(shí)現(xiàn)形態(tài)學(xué)圖像處理

    這篇文章主要為大家介紹了matlab實(shí)現(xiàn)形態(tài)學(xué)圖像處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • C++按位異或運(yùn)算符的使用介紹

    C++按位異或運(yùn)算符的使用介紹

    本篇文章對C++按位異或運(yùn)算符的使用進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下
    2013-05-05
  • C語言圖書借閱系統(tǒng)源碼

    C語言圖書借閱系統(tǒng)源碼

    這篇文章主要為大家分享了C語言圖書借閱系統(tǒng)源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • c++實(shí)現(xiàn)值機(jī)系統(tǒng)

    c++實(shí)現(xiàn)值機(jī)系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了c++實(shí)現(xiàn)在線值機(jī)系統(tǒng)程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C/C++高精度運(yùn)算(大整數(shù)運(yùn)算)詳細(xì)講解

    C/C++高精度運(yùn)算(大整數(shù)運(yùn)算)詳細(xì)講解

    高精度算法的本質(zhì)是把大數(shù)拆成若干固定長度的塊,然后對每一塊進(jìn)行相應(yīng)的運(yùn)算,下面這篇文章主要給大家介紹了關(guān)于C/C++高精度運(yùn)算(大整數(shù)運(yùn)算)的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • c++迭代器失效的情況匯總

    c++迭代器失效的情況匯總

    這篇文章主要介紹了C++迭代器失效的幾種情況總結(jié),文中代碼非常詳細(xì),幫助大家更好的了解學(xué)習(xí),感興趣的朋友可以參考下
    2020-06-06
  • C++中for auto的用法及說明

    C++中for auto的用法及說明

    這篇文章主要介紹了C++中for auto的用法及說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C++模板template用法小結(jié)(推薦)

    C++模板template用法小結(jié)(推薦)

    這篇文章主要介紹了C++模板template用法總結(jié) ,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03

最新評論