有以下三種方式可以使用shared_ptr
1. 如果你的c++編程環境支持c++標準,那么可以直接使用 std::shared_ptr,它定義在memory文件中。
2. 如果你的c++實現支持 C++TR1庫擴展,那么可以使用 std::tr1::shared_ptr。在Vc++編譯器下是在 <memory>定義,如果是linux下g++,那么定義在 <tr1/memory>文件中。Boost也提供了TR1實現。
3. 否則的話,你可以使用Boost中的 boost::shared_ptr,它定義在 <boost/shared_ptr.hpp>文件中。
(1)刪除共享對象
使用shared_ptr解決的主要問題是知道刪除一個被多個客戶共享的資源的正確時機。下面是一個簡單易懂的例子,有兩個類A和 B, 它們共享一個int實例。使用boost::shared_ptr,你需要必須包含"boost/shared_ptr.hpp".
#include"boost/shared_ptr.hpp" #include<cassert> classA { boost::shared_ptr<int>no_; public: A(boost::shared_ptr<int>no) : no_(no) {} voidvalue(int i) { *no_=i; } }; classB { boost::shared_ptr<int>no_; public: B(boost::shared_ptr<int>no) : no_(no) {} intvalue() const { return*no_; } }; intmain() { boost::shared_ptr<int>temp(new int(14)); Aa(temp); Bb(temp); a.value(28); assert(b.value()==28); }
類 A和 B都保存了一個shared_ptr<int>.在創建A和 B的實例時,shared_ptrtemp被傳送到它們的構造函數。這意味著共有三個shared_ptr:a,b,和 temp,它們都引向同一個int實例。如果我們用指針來實現對一個的共享,A和 B必須能夠在某個時間指出這個int要被刪除。在這個例子中,直到main的結束,引用計數為3,當所有shared_ptr離開了作用域,計數將達到0,而一個智能指針將負責刪除共享的 int.
(2)標準容器
把對象直接存入容器中有時會有些麻煩。以值的方式保存對象意味著使用者將獲得容器中的元素的拷貝,對于那些復制是一種昂貴的操作的類型來說可能會有性能的問題。此外,有些容器,特別是std::vector,當你加入元素時可能會復制所有元素,這更加重了性能的問題。,傳值的語義意味著沒有多態的行為。如果你需要在容器中存放多態的對象而且你不想切割它們,你必須用指針。如果你用裸指針,維護元素的完整性會非常復雜。從容器中刪除元素時,你必須知道容器的使用者是否還在引用那些要刪除的元素,不用擔心多個使用者使用同一個元素。這些問題都可以用shared_ptr來解決。
下面是如何把共享指針存入標準庫容器的例子。
#include"boost/shared_ptr.hpp" #include<vector> #include<iostream> classA { public: virtualvoid sing()=0; protected: virtual~A() {}; }; classB : public A { public: virtualvoid sing() { std::cout<< "Do re mi fa so la"; } }; boost::shared_ptr<A>createA() { boost::shared_ptr<A>p(new B()); returnp; } intmain() { typedefstd::vector<boost::shared_ptr<A> > container_type; typedefcontainer_type::iterator iterator; container_typecontainer; for(int i=0;i<10;++i) { container.push_back(createA()); } std::cout<< "The choir is gathered: n"; iteratorend=container.end(); for(iterator it=container.begin();it!=end;++it) { (*it)->sing(); }
}這里有兩個類, A和 B,各有一個虛擬成員函數 sing. B從 A公有繼承而來,并且如你所見,工廠函數 createA返回一個動態分配的B的實例,包裝在shared_ptr<A>里。在 main里,一個包含shared_ptr<A>的std::vector被放入10個元素,對每個元素調用sing。如果我們用裸指針作為元素,那些對象需要被手工刪除。而在這個例子里,刪除是自動的,因為在vector的生存期中,每個shared_ptr的引用計數都保持為1;當 vector被銷毀,所有引用計數器都將變為零,所有對象都被刪除。有趣的是,即使A的析構函數沒有聲明為virtual,shared_ptr也會正確調用B的析構函數!
上面的例子示范了一個強有力的技術,它涉及A里面的protected析構函數。因為函數 createA返回的是shared_ptr<A>,因此不可能對shared_ptr::get返回的指針調用 delete。這意味著如果為了向某個需要裸指針的函數傳送裸指針而從shared_ptr中取出裸指針的話,它不會由于意外地被刪除而導致災難。那么,又是如何允許shared_ptr刪除它的對象的呢?這是因為指針指向的真正類型是B;而B的析構函數不是protected的。這是非常有用的方法,用于給shared_ptr中的對象增加額外的安全性。
想學習更多的c++語言技術那就加入我們吧!