国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

C++箴言:資源管理類(lèi)的拷貝行為

2019-11-17 05:38:05
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  在上一篇文章中介紹了作為資源治理類(lèi)支柱的 Resource Acquisition Is Initialization (RAII) 原則,并描述了 auto_ptr 和 tr1::shared_ptr 在基于堆的資源上運(yùn)用這一原則的表現(xiàn)。并非所有的資源都是基于堆的,然而,對(duì)于這樣的資源,像 auto_ptr 和 tr1::shared_ptr 這樣的智能指針通常就不像 resource handlers(資源治理者)那樣合適。在這種情況下,有時(shí),你可能要根據(jù)你自己的需要去創(chuàng)建你自己的資源治理類(lèi)。

  例如,假設(shè)你使用 C API 提供的 lock 和 unlock 函數(shù)去操縱 Mutex 類(lèi)型的互斥體對(duì)象:

  

  void lock(Mutex *pm); // lock mutex pointed to by pm

  

  void unlock(Mutex *pm); // unlock the mutex

  為了確保你從不會(huì)忘記解鎖一個(gè)被你加了鎖的 Mutex,你希望創(chuàng)建一個(gè)類(lèi)來(lái)治理鎖。RAII 原則規(guī)定了這樣一個(gè)類(lèi)的基本結(jié)構(gòu),通過(guò)構(gòu)造函數(shù)獲取資源并通過(guò)析構(gòu)函數(shù)釋放它:

  

  class Lock {

   public:

    eXPlicit Lock(Mutex *pm)

    : mutexPtr(pm)

    { lock(mutexPtr); } // acquire resource

   

    ~Lock() { unlock(mutexPtr); } // release resource

  

   PRivate:

    Mutex *mutexPtr;

  };

  客戶(hù)按照 RAII 風(fēng)格的慣例來(lái)使用 Lock:

  

  Mutex m; // define the mutex you need to use

  ...

  { // create block to define critical section

   Lock ml(&m); // lock the mutex

   ... // perform critical section Operations

  

  } // automatically unlock mutex at end

  // of block

  這沒(méi)什么問(wèn)題,但是假如一個(gè) Lock 對(duì)象被拷貝應(yīng)該發(fā)生什么?
  Lock ml1(&m); // lock m

  

  Lock ml2(ml1); // copy ml1 to ml2-what should

  // happen here?

  這是一個(gè)更一般問(wèn)題的特定實(shí)例,每一個(gè) RAII 類(lèi)的作者都要面臨這樣的問(wèn)題:當(dāng)一個(gè) RAII 對(duì)象被拷貝的時(shí)候應(yīng)該發(fā)生什么?大多數(shù)情況下,你可以從下面各種可能性中挑選一個(gè):

  禁止拷貝。在很多情況下,答應(yīng) RAII 被拷貝是沒(méi)有意義的。這對(duì)于像 Lock 這樣類(lèi)很可能是正確的,因?yàn)橥降幕疽氐摹案北尽焙苌儆惺裁匆饬x。當(dāng)拷貝對(duì)一個(gè) RAII 類(lèi)沒(méi)有什么意義的時(shí)候,你應(yīng)該禁止它。Item 6 解釋了如何做到這一點(diǎn)。聲明拷貝操作為私有。對(duì)于 Lock,看起來(lái)也許像這樣:

  

  class Lock: private Uncopyable { // prohibit copying - see

  public: // Item 6

  ... // as before

  };

  對(duì)底層的資源引用計(jì)數(shù)。有時(shí)人們需要的是保持一個(gè)資源直到最后一個(gè)使用它的對(duì)象被銷(xiāo)毀。在這種情況下,拷貝一個(gè) RAII 對(duì)象應(yīng)該增加引用這一資源的對(duì)象的數(shù)目。這也就是使用 tr1::shared_ptr 時(shí)“拷貝”的含意。

  通常,RAII 類(lèi)只需要包含一個(gè) tr1::shared_ptr 數(shù)據(jù)成員就能夠?qū)崿F(xiàn)引用計(jì)數(shù)的拷貝行為。例如,假如 Lock 要使用引用計(jì)數(shù),他可能要將 mutexPtr 的類(lèi)型從 Mutex* 改變?yōu)?tr1::shared_ptr。不幸的是,tr1::shared_ptr 的缺省行為是當(dāng)它所指向的東西的引用計(jì)數(shù)變?yōu)?0 的時(shí)候?qū)⑺鼊h除,但這不是我們要的。當(dāng)我們使用 Mutex 完畢后,我們想要將它解鎖,而不是將它刪除。

  幸運(yùn)的是,tr1::shared_ptr 答應(yīng)一個(gè) "deleter" 規(guī)范——當(dāng)引用計(jì)數(shù)變?yōu)?0 時(shí)調(diào)用的一個(gè)函數(shù)或者函數(shù)對(duì)象。(這一功能是 auto_ptr 所沒(méi)有的,auto_ptr 總是刪除它的指針。)deleter 是 tr1::shared_ptr 的構(gòu)造函數(shù)的可選的第二個(gè)參數(shù),所以,代碼看起來(lái)就像這樣:

  

  class Lock {

  public:

   explicit Lock(Mutex *pm) // init shared_ptr with the Mutex

   : mutexPtr(pm, unlock) // to point to and the unlock func

   { // as the deleter

  lock(mutexPtr.get()); // see Item 15 for info on "get"

   }

  private:

   std::tr1::shared_ptr mutexPtr; // use shared_ptr

  }; // instead of raw pointer

  在這個(gè)例子中,注重 Lock 類(lèi)是如何不再聲明一個(gè)析構(gòu)函數(shù)的。那是因?yàn)樗辉傩枰tem 5 解釋了一個(gè)類(lèi)的析構(gòu)函數(shù)(無(wú)論它是編譯器生成還是用戶(hù)定義)會(huì)自動(dòng)調(diào)用這個(gè)類(lèi)的非靜態(tài)(non-static)數(shù)據(jù)成員的析構(gòu)函數(shù)。在本例中,就是 mutexPtr。但是,當(dāng)互斥體的引用計(jì)數(shù)變?yōu)?0 時(shí),mutexPtr 的析構(gòu)函數(shù)會(huì)自動(dòng)調(diào)用的是 tr1::shared_ptr 的 deleter ——在此就是 unlock。(看過(guò)這個(gè)類(lèi)的源代碼的人多半意識(shí)到需要增加一條注釋表明你并非忘記了析構(gòu),而只是依靠編譯器生成的缺省行為。)

  拷貝底層的資源。有時(shí)就像你所希望的你可以擁有一個(gè)資源的多個(gè)副本,唯一的前提是你需要一個(gè)資源治理類(lèi)確保當(dāng)你使用完它之后,每一副本都會(huì)被釋放。在這種情況下,拷貝一個(gè)資源治理對(duì)象也要同時(shí)拷貝被它隱藏的資源。也就是說(shuō),拷貝一個(gè)資源治理類(lèi)需要完成一次“深層拷貝”。

  某些標(biāo)準(zhǔn) string 類(lèi)型的實(shí)現(xiàn)是由堆內(nèi)存的指針組成,堆內(nèi)存中存儲(chǔ)著組成那個(gè) string 的字符。這樣的字符串對(duì)象包含指向堆內(nèi)存的指針。當(dāng)一個(gè) string 對(duì)象被拷貝,這個(gè)副本應(yīng)該由那個(gè)指針和它所指向的內(nèi)存組成。這樣的 strings 表現(xiàn)為深層拷貝。

  傳遞底層資源的所有權(quán)。在某些非凡場(chǎng)合,你可能希望確保只有一個(gè) RAII 對(duì)象引用一個(gè)未加工的資源,而當(dāng)這個(gè) RAII 對(duì)象被拷貝的時(shí)候,資源的所有權(quán)從被拷貝的對(duì)象傳遞到拷貝對(duì)象。就像上一篇文章所說(shuō)明的,這就是使用 auto_ptr 時(shí)“拷貝”的含意。

  拷貝函數(shù)(copying functions)(拷貝構(gòu)造函數(shù)和拷貝賦值運(yùn)算符)可能是由編譯器生成的,所以除非編譯器生成的版本所做的事正是你所要的,你應(yīng)該自己編寫(xiě)它們。在某些情況下,你也要支持這些函數(shù)的泛型化版本。

  Things to Remember

  ·拷貝一個(gè) RAII 對(duì)象必須拷貝它所治理的資源,所以資源的拷貝行為決定了 RAII 對(duì)象的拷貝行為。

  ·普通的 RAII 類(lèi)的拷貝行為不接受拷貝和進(jìn)行引用計(jì)數(shù),但是其它行為是有可能的。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 朔州市| 定结县| 太原市| 伊宁市| 巢湖市| 高清| 泌阳县| 浑源县| 新蔡县| 金乡县| 阳新县| 德昌县| 射洪县| 乐业县| 社会| 兰州市| 拉孜县| 获嘉县| 会理县| 泸州市| 苏尼特右旗| 瑞金市| 固阳县| 永顺县| 习水县| 普格县| 佛冈县| 丹阳市| 剑阁县| 海丰县| 仁寿县| 普格县| 临高县| 喜德县| 湖南省| 云浮市| 陵水| 海盐县| 三门峡市| 施秉县| 隆子县|