智慧指標學習
轉自:http://blog.csdn.net/linfengfeiye/article/details/4054258
最近接觸到智慧指標很多,於是研究了一下智慧指標的原理,寫下自己的心得體會,有不對的還請指正。
智慧指標產生的目的:因為在C++中,存在非常複雜的指標錯誤問題,例如,某個物件生成後,指向該物件的指標可能有多個,當我們用delete語句刪除其中的一個指標後,物件就被銷燬,那麼其餘指向該物件的指標就會懸空,這樣很容易出錯記憶體誤,為避免出現這樣的問題,出現了智慧指標,智慧指標有2種構造方法,一種是插入式的還有一種是非插入式的,非插入式指標一般是直接採用裸指標作為引數進行建立,不需要修改現有的物件程式碼,而插入式是採用一個公用的有數量統計功能的基類來派生需要智慧指標的類,相對來說,插入式構造方法將需要更多的額外空間,而且需要修改原類。非插入式智慧指標(shared_ptr)可以從裸指標,另一個shared_ptr、一個std::auto_ptr、或者一個boost::weak_ptr來構造,還可以傳遞第二個引數給shared_ptr的建構函式,它被稱為刪除器(deleter)。刪除器稍後會被呼叫,來處理共享資源的釋放。這對於管理那些不是用new分配也不是用delete釋放的資源時非常有用。shared_ptr被建立後,它就可象普通指標一樣使用了,除了一點,它不能被顯式地刪除,列舉一個shared_ptr的例子,有時候把物件直接存入容器中有時會有些麻煩,以值的方式儲存物件意味著使用者將獲得容器中的元素的拷貝,對於那些複製是一種昂貴的操作的型別來說可能會有效能的問題。此外,有些容器,特別是std::vector, 當你加入元素時可能會複製所有元素,這更加重了效能的問題。最後,傳值的語義意味著沒有多型的行為。如果你需要在容器中存放多型的物件而且你不想切割它們,你必須用指標。如果你用裸指標,維護元素的完整性會非常複雜。從容器中刪除元素時,你必須知道容器的使用者是否還在引用那些要刪除的元素,不用擔心多個使用者使用同一個元素。這些問題都可以用shared_ptr來解決。插入式版本。有時我們必須使用插入式的引用計數智慧指標。典型的情況是對於那些已經寫好了內部引用計數器的程式碼,而我們又沒有時間去重寫它(或者已經不能獲得那些程式碼了)。另一種情況是要求智慧指標的大小必須與裸指標大小嚴格相等,或者shared_ptr的引用計數器分配嚴重影響了程式的效能(這是非常罕見的情況!)。從功能的觀點來看,唯一需要插入式智慧指標的情況是,被指類的某個成員函式需要返回this,以便它可以用於另一個智慧指標(事實上,也有辦法使用非插入式智慧指標來解決這個問題)。intrusive_ptr 不同於其它智慧指標,因為它要求你來提供它所要的引用計數器。當 intrusive_ptr 遞增或遞減一個非空指標上的引用計數時,它是通過分別呼叫函式intrusive_ptr_add_ref 和 intrusive_ptr_release來完成的。這兩個函式負責確保引用計數的正確性,並且負責在引用計數降為零時刪除指標。因此,你必須為你的類過載這兩個函式。
下面是部分實現原始碼:
非插入式版本:
namespace boost { template<typename T> class shared_ptr { public: template <class Y> explicit shared_ptr(Y* p); //從裸露指標構造 template <class Y,class D> shared_ptr(Y* p,D d); //從裸露指標構造,同時指定刪除器 ~shared_ptr(); shared_ptr(const shared_ptr & r); //從另一個指標指標構造template <class Y> explicit shared_ptr(const weak_ptr<Y>& r);//從弱指標構造 template <class Y> explicit shared_ptr(std::auto_ptr<Y>& r);//從自動指標構造 shared_ptr& operator=(const shared_ptr& r);
void reset();//用於停止對儲存指標的所有權的共享。共享資源的引用計數減一 T& operator*() const; T* operator->() const; T* get() const; bool unique() const; long use_count() const; operator unspecified_bool_type() const; void swap(shared_ptr<T>& b); }; template <class T,class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r); }
插入式版本(只列出了最重要的函式)
namespace boost {
template<class T> class intrusive_ptr {
public:
intrusive_ptr(T* p,bool add_ref=true);
intrusive_ptr(const intrusive_ptr& r);
~intrusive_ptr();
T& operator*() const;
T* operator->() const;
T* get() const;
operator unspecified-bool-type() const;
};
template <class T> T* get_pointer(const intrusive_ptr<T>& p);
template <class T,class U> intrusive_ptr<T>
static_pointer_cast(const intrusive_ptr<U>& r);
使用intrusive_ptr與使用shared_ptr相比,有兩個主要的不同之處。第一個是你需要提供引用計數的機制。第二個是把this當成智慧指標是合法的[12],正如我們即將看到的,有時候這樣很方便。注意,在多數情況下,應該使用非插入式的 shared_ptr.你不能用shared_ptr 來做到這一點,如果沒有進行特殊處理的話,如 enable_shared_from_this.要使用 boost::intrusive_ptr, 要包含 "boost/intrusive_ptr.hpp" 並定義兩個普通函式 intrusive_ptr_add_ref 和 intrusive_ptr_release. 它們都要接受一個引數,即指向你要使用intrusive_ptr的型別的指標。這兩個函式的返回值被忽略。通常的做法是,泛化這兩個函式,簡單地呼叫被管理型別的成員函式去完成工作(例如,呼叫 add_ref 和 release)。如果引用計數降為零,intrusive_ptr_release 應該負責釋放資源。以下是你應該如何實現這兩個泛型函式的示範:
template <typename T> void intrusive_ptr_add_ref(T* t) {
t->add_ref();
}
template <typename T> void intrusive_ptr_release(T* t) {
if (t->release()<=0)
delete t;
}
注意,這兩個函式應該定義在它們的引數型別所在的作用域內。這意味著如果這個函式接受的引數型別來自於一個名字空間,則函式也必須定義在那裡。這樣做的原因是,函式的呼叫是非受限的,即允許採用引數相關查詢,而如果有多個版本的函式被提供,那麼全部名字空間肯定不是放置它們的好地方。我們稍後將看到一個關於如何放置它們的例子,但首先,我們需要提供某類的引用計數器。
explicit關鍵字:
c++中的explicit關鍵字用來修飾類的建構函式,表明該建構函式是顯式的,既然有"顯式"那麼必然就有"隱式",那麼什麼是顯示而什麼又是隱式的呢?如果c++類的建構函式有一個引數,那麼在編譯的時候就會有一個預設的轉換操作:將該建構函式對應資料型別的資料轉換為該類物件,如下面所示: class MyClass { public: MyClass( int num ); } .... MyClass obj = 10; //ok,convert int to MyClass 在上面的程式碼中編譯器自動將整型轉換為MyClass類物件,實際上等同於下面的操作: MyClass temp(10); MyClass obj = temp; 上面的所有的操作即是所謂的"隱式轉換"。
未完待續。。。。。
相關文章
- 智慧指標用法學習指標
- 智慧指標引用計數變化學習指標
- C++智慧指標學習——小談引用計數C++指標
- 指標學習筆記指標筆記
- 智慧指標指標
- go 語言指標學習Go指標
- day1 指標學習指標
- C語言指標學習C語言指標
- [CPP] 智慧指標指標
- Golang 學習——陣列指標和指標陣列的區別Golang陣列指標
- 什麼是智慧指標?為什麼要用智慧指標?指標
- 機器學習之迴歸指標機器學習指標
- C++智慧指標C++指標
- openfoam 智慧指標探索指標
- 智慧指標之手撕共享指標shared_ptr指標
- 物聯網學習教程—字串與指標字串指標
- 日常學習儲存--陣列和指標陣列指標
- C語言學習之:指標與字串C語言指標字串
- UE4 智慧指標指標
- 徹底學會 Go 指標 -- 就要學習 Go 語言Go指標
- C++ 學習筆記(3):引用和指標C++筆記指標
- 指標+AI:邁向智慧化,讓指標應用更高效指標AI
- C++ 用智慧指標這樣包裝 this 指標是否可行C++指標
- C++11智慧指標用法C++指標
- C++進階(智慧指標)C++指標
- 智慧指標和普通指標的區別指標
- 機器學習中的效能度量指標彙總機器學習指標
- 笨辦法學C 練習18:函式指標函式指標
- 機器學習筆記之效能評估指標機器學習筆記指標
- C++標準庫有四種智慧指標C++指標
- c++ 智慧指標用法詳解C++指標
- C++筆記(11) 智慧指標C++筆記指標
- C指標-這該死的嵌入式學習生涯指標
- C語言學習筆記之指標的運算C語言筆記指標
- 物聯網學習教程— 多維陣列與指標陣列指標
- C語言學習筆記:結構體與指標C語言筆記結構體指標
- 雙指標習題:Kalindrome Array指標
- 函式指標練習題函式指標
- 智慧指標-使用、避坑和實現指標