shared ptr 兩種常見的使用方式 1

2021-04-12 17:07:41 字數 3137 閱讀 3156

roger(

[email protected]

1.當作類物件的「共享控制代碼」來使用

2.在類內部提供資源管理服務 —— 「為類提供資源的共享拷貝語義

(或稱為淺拷貝

shadow copy

),並在正確的時間**資源」

上述的兩種方式一種是在類外部使用,一種是在類內部使用,然而這兩種方式並不是非此即彼的關係,很多情況下我們都可以選擇任意一種,選擇其中一種理由通常是遵循「更容易被使用,更難以被誤用」的原則。

當作類物件的「共享控制代碼」來使用

在這種使用方式下,結合create method模式使用會取得更好的效果

(關於create method

模式,更多資訊請看「模式與重構一書」)。

以下是乙個使用場景,我們有乙個類,類封裝了乙個底層資源的控制代碼和跟控制代碼相關的所有api呼叫

(控制代碼和

api呼叫來自作業系統或者其它的

c函式庫)。

控制代碼在不再被使用的時候需要被釋放

(析構函式是最適合做這件事的,不是嗎?);

控制代碼的拷貝可能是一種危險的行為

(通常控制代碼的實現都是所謂的

opaque pointer

不透明指標,也是說該指標實際是指向一塊

api操作的資料結構,只是該資料結構是不對外公開的,這也是所謂的c-

oo風格),因為有可能導致懸掛控制代碼

(其實也是懸掛指標)或者由於釋放的責任模糊而導致重複釋放。

所以,我們用類封裝底層資源控制代碼,但不為該類提供拷貝行為,而是通過外裹的share_ptr來提供共享拷貝語義。

下面是乙個實際例子,來自我自己封裝lcms庫profile控制代碼的乙個類

(lcms

是乙個開源用於色彩管理的

c函式庫,也是乙個輕量級可用於學習

c-oo

程式設計的不錯選擇),cmshprofile是lcms的profile

(特性檔案)資源控制代碼。

kprofile.h

#pragma

once

#include 

"kprofileshptr.h

"#include 

<

lcms

/lcms.h

>

namespace

milk

/** print out 

*/ostream

&print(ostream&) 

const;/*

* basic information related function. 

*/string

getproductname() 

const

;string

getproductdescription() 

const

;string

getproductinformation() 

const

;string

getmanufacturer() 

const

;string

getmodel() 

const

;string

const

;uint32               getprofileversion() 

const

;string

getprofileversionstring() 

const

;private

:kprofile();

kprofile(cmshprofile);

kprofile(

const

char*, 

const

char*);

kprofile(

void

*, uint32);

cmshprofile       handle_;};}

1.kprofile 封裝了cmshprofile(

handle_

)控制代碼,和許多相關的lcms api呼叫 2.

從boost庫的noncopyable獲得禁止拷貝的行為(拷貝建構函式和賦值操作符)

3.kprofile不提供public的建構函式,而是提供一系列的create methods,所有的create methods都返回kprofileshptr(

typedef boost::shared_ptrkprofileshptr)4.

gethandle函式會返回內部profile控制代碼(資源封裝類應該允許返回內部的控制代碼或者指標,參看

effective c++

第三版)

kprofileshptr.h

#pragma

once 

namespace

milk

1.另外提供乙個kprofileshptr.h而不把typedef置於kprofile.h內的原因是為了提供kprofileshptr的前置宣告

(類似c++標準庫

iosfwd

的做法),就是說當其它類的介面需要使用到kprofileshptr的時候,它不必在標頭檔案中包括kprofile.h,而只需要包括kprofileshptr.h即可。(當然在所有的地方都寫boost::shared_ptr可以免除這種麻煩,看個人喜好)

kprofile.cpp

#include 

"kprofile.h

"#include 

"kcm***ception.h

"namespace

milk

kprofile::kprofile(cmshprofile handle)

: handle_(handle)

kprofile::

~kprofile(

void

)kprofileshptr

kprofile::createfromhandle(cmshprofile handle)}

1.在析構函式中會釋放profile控制代碼

2.由於kprofile沒有提供拷貝行為,所以析構函式不會擔心會多次釋放同一控制代碼,當然如果釋放發生在類外部,這不是類kprofile可以控制的

TabWidget TabHost的兩種使用方法

android tabwidget tabhost有兩種使用方法 第一種 使用系統自帶寫好的tabhost 及繼承自tabactivity類 具體 如下 package com.aina.android import android.content.dialoginte ce import andr...

angularjs的 filter的兩種使用

我們可以直接在 中使用filter,跟在表示式後面用 分割,語法如下 filter可以接收引數,引數用 進行分割,如下 除了對 中的資料進行格式化,我們還可以在指令中使用filter,例如先對陣列array進行過濾處理,然後再迴圈輸出 我們的js 中也可以使用過濾器,方式就是我們熟悉的依賴注入,例如...

XML的兩種常見格式

寫了好長時間感覺sax解析也不難理解,主要是xml文件的格式我們不熟悉,熟悉了xml文件的格式,再來看sax解析就好多了 所以寫了這篇關於xml文件常見的兩種格式的詳細解讀 先來模擬一下兩種格式 xml第一種形式 此時我們需要解析的是元素 元素屬性 下面是nsparser的幾個 方法,給出列印結果,...