程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++智能指針念書筆記

C++智能指針念書筆記

編輯:關於C++

C++智能指針念書筆記。本站提示廣大學習愛好者:(C++智能指針念書筆記)文章只能為提供參考,不一定能成為您想要的結果。以下是C++智能指針念書筆記正文


比來在補看《C++ Primer Plus》第六版,這切實其實是本好書,個中關於智能指針的章節解析的異常清楚,一解我之前的多處迷惑。C++面試進程中,許多面試官都愛好問智能指針相干的成績,好比你曉得哪些智能指針?shared_ptr的設計道理是甚麼?假如讓你本身設計一個智能指針,你若何完成?等等……。並且在看開源的C++項目時,也能到處看到智能指針的影子。這解釋智能指針不只是面試官愛問的題材,更長短常有適用價值。

C++經由過程一對運算符 new 和 delete 停止靜態內存治理,new在靜態內存中為對象分派空間並前往一個指向該對象的指針,delete接收一個靜態對象的指針,燒毀對象並釋放與之相干的內存。但是如許的靜態內存的應用很風險,由於沒法確保一直能在適合的時光釋放內存對象。假如忘卻釋放內存,能夠形成內存洩漏;假如在另有指針援用內存的情形下釋放內存,會發生不法拜訪內存的指針。

C++11中,新的尺度庫供給了兩種智能指針(smart pointer)類型來更平安地治理對象。智能指針的應用和慣例指針相似,只是它們多了主動釋放所指向的對象的功效。兩種指針的差別在於治理底層指針的方法:shared_ptr許可多個指針指向統一個對象,unique_ptr不支撐。尺度庫還供給了weak_ptr這一弱指針,指向shared_ptr所治理的對象。三品種型都界說在頭文件memory中。

shared_ptr的應用和vector很類似,在尖括號內解釋所指向對象的類型:

shared_ptr<string> p1              // p1是shared_ptr,指向string類型
shared_ptr<list<int>> p2     // p2是shared_ptr,指向list的int

解援用一個智能指針就可以取得它所指向的對象,在if語句中應用智能指針可以斷定它指向的對象能否為空:

// 假如p1非空,檢討p1能否指向一個空的string對象
if (p1 && p1->empty())
    *p1 = "creat";        // 假如p1非空且指向一個空的string對象,解援用p1,為其賦新值creat

最平安的分派和應用shared_ptr的辦法是挪用名為make_shared這一尺度庫函數。此函數在靜態內存平分配並初始化它,前往指向此對象的shared_ptr。該函數界說在memory中。

make_shared的界說和shared_ptr類似,必需制訂要創立對象的類型,如:

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

也能夠應用auto界說對象保留make_shared,可以省去書寫shared_ptr的費事。

  shared——ptr中有一個聯系關系的指導器,稱為援用計數。可以看作一個計數器,每當shared_ptr對象停止拷貝操作,如用一個shared_ptr對象初始化另外一個shared_ptr對象、作為函數的實參、作為函數前往值時,援用計數都邑遞增(視為數值+1)。當付與shared_ptr新值或許shared_ptr被燒毀時,援用計數遞加。當援用計數減為0,經由過程析構函數,shared_ptr主動燒毀所治理的對象,釋放內存。

  須要留意的是,假如多個對象同享底層數據,當某一對象被燒毀,不克不及片面燒毀底層數據,例如:

Blob<string> b1;
{ // 新感化域
  Blob<string> b2 = { "x", "b", "b" };
  b1 = b2;
}  // 當分開部分感化域,b2被燒毀,但是b2中的元素xbb其實不會被燒毀
   // b1指向最後由b2創立的元素,即“x”, "b", "b",b1照舊可以它們

  weak_ptr是指向shared_ptr治理的對象的一種智能指針,但是它不掌握所指向對象的生計期。將一個weak_ptr綁定在shared_ptr上,不會轉變shared_ptr的援用計數,一旦最初一個shared_ptr的指向對象被摧燒毀,對象就會被釋放,有沒有weak_ptr並沒有卵影響。我的懂得是,weak_ptr供給了指向shared_ptr底層數據的功效,掌握了shared_ptr對底層數據的拜訪。

  由於weak_ptr指向的對象能夠不存在(shared_ptr指向的最初一個對象被燒毀時),因此用它不克不及直接拜訪對象,必需挪用lock函數檢討其指向的對象能否存在。很輕易寫出一個選擇語句停止掌握:

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

彌補weak_ptr相干的函數,便於懂得:

w.reset 將w置為空
w.use_count() 與w同享對象的個數
w.expired() 若w.use_count()為0,前往true,不然前往false
w.lock() 若w.expired()為true,前往一個空shared_ptr,不然前往一個指向w的對象的shared_ptr

參加《C++ Primer 5th》中的12.19題參照,題中和“智能指針和異常”並未在本篇漫筆中引見

#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();          // 前往一個指向它本身的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)) {};  // 接收一個initializer_list參數的結構函數將其參數傳                                                            遞給對應的vector結構函數,經由過程拷貝列表
  StrBlob::StrBlob() : data(make_shared<vector<string>>()) {};                 // 結構函數,初始化data成員,指向靜態分派的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勝利,前往一個p指針,指向make_shared指向的vector
  }            // 解援用,make_shared獲得vector,用下表運算符前往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());
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved