原文連接html
模版類 shared_ptr 存儲動態構造對象的指針,一般是由C++ new語句完成的。這個對象指針在最後一個持有指針全部權的shared_ptr被銷燬或者重置(reset)的時候,指針被delete。c++
例1: 使用 shared_ptr數組
shared_pt<X> p1( new X );
shared_ptr<void> p2( new int(5) );安全
shared_ptr 會使用構造時的原始類型從而正確的刪除指針,無論模版類型是什麼。在例1,p2被銷燬或者重置(reset)的時候,會調用delete操做法刪除int*類型指針,即便模版類型是void,shared_ptr存儲的也是void*類型的指針。函數
shared_ptr 知足C++標準庫拷貝構造、移動構造、拷貝賦值和移動賦值的需求,也能夠用在C++標準庫容器上。也提供了比較操做,因此shared_ptr也能夠用在C++標準庫關聯容器上。this
因爲shared_ptr實現上採用了引用計數,循環引用將致使資源不能正確的回收。例如shared_ptr對象A,不論是直接或間接返回對象A,A的引用計數會變成2。析構對象A引用計數變成1,不會去釋放資源。使用 weak_ptr 能夠避免循環引用。atom
shared_ptr類的模版參數T,是指向的對象的類型,其大部分紅員函數不要求模版參數T。能夠是不完整的類型或 void 類型。構造函數和reset須要顯示地指出新的參數類型。spa
當 T* 能夠隱式轉換成 U* 時,shared_ptr<T>也能夠隱式轉換成shared_ptr<U>。尤爲是shared_ptr<T>隱式轉換成shared_ptr<T const>、shared_ptr<U>(類型U是類型T的可訪問基類)、shared_ptr<void>。指針
shared_ptr 在C++11標準上被命名爲 std::shared_ptr。code
隨着boost 1.53版本,shared_ptr 能夠存儲動態分配的數組,可使用數組類型(T[]/T[N])做爲模版參數。使用不定數量當數組T[]和必定數量的數組T[N],幾乎是沒有區別的;後者可以使用operator[]對索引(index)執行範圍檢查。
例2:使用數組類型的shared_ptr
shared_ptr<double[1024]> p1( new double[1024] );
shared_ptr<double[]> p2( new double[] );
一個簡單的消除內存泄漏的可能的指導是老是使用命名的智能指針變量去存儲new操做返回的指針對象。每一個使用new的代碼都應該是下面這種類型:
shared_ptr
p(new Y);
固然可使用另外一種智能指針類型代替上面的shared_ptr,T和Y能夠是相同的類型,h或傳遞參數給Y的構造函數也是能夠的。
若是你遵照這個規則,很顯然你不須要顯示delete語句,try/catch結構也會不多。
避免使用不命名的shared_ptr臨時變量去保存類型,要了解爲何這是危險的,請考慮這個例子:
例3:使用shared_ptr的異常安全和不安全
void f(shared_ptr<int>, int); int g(); void ok() { shared_ptr<int> p(new int(2)); f(p, g()); } void bad() { f(shared_ptr<int>(new int(2)), g()); }
函數 ok 是正確使用智能指針的方式,而 bad 使用 shared_ptr 臨時變量的形式存在內存泄漏的可能。由於函數參數的計算順序是未知的,多是先計算 new int(2),而後 g(),若是函數g拋出異常,就不會構造shared_ptr對象。關於這個問題的更多信息能夠點擊Herb Sutter’s treatment
上述異常安全的問題也可使用工廠函數(make_shared/allocate_shared),這兩個函數定義在<boost/smart_ptr/make_shared.hpp>。這兩個工廠函數還能保證效率上的提高。
shared_ptr 定義在 <boost/smart_ptr/shared_ptr.hpp>
namespace boost { class bad_weak_ptr: public std::exception; template<class T> class weak_ptr; template<class T> class shared_ptr { public: typedef /*see below*/ element_type; constexpr shared_ptr() noexcept; constexpr shared_ptr(std::nullptr_t) noexcept; template<class Y> explicit shared_ptr(Y * p); template<class Y, class D> shared_ptr(Y * p, D d); template<class Y, class D, class A> shared_ptr(Y * p, D d, A a); template<class D> shared_ptr(std::nullptr_t p, D d); template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a); ~shared_ptr() noexcept; shared_ptr(shared_ptr const & r) noexcept; template<class Y> shared_ptr(shared_ptr<Y> const & r) noexcept; shared_ptr(shared_ptr && r) noexcept; template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept; template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept; template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept; template<class Y> explicit shared_ptr(weak_ptr<Y> const & r); template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r); template<class Y> shared_ptr(std::auto_ptr<Y> && r); template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r); shared_ptr & operator=(shared_ptr const & r) noexcept; template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) noexcept; shared_ptr & operator=(shared_ptr const && r) noexcept; template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r) noexcept; template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r); template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r); template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r); shared_ptr & operator=(std::nullptr_t) noexcept; void reset() noexcept; template<class Y> void reset(Y * p); template<class Y, class D> void reset(Y * p, D d); template<class Y, class D, class A> void reset(Y * p, D d, A a); template<class Y> void reset(shared_ptr<Y> const & r, element_type * p) noexcept; template<class Y> void reset(shared_ptr<Y> && r, element_type * p) noexcept; T & operator*() const noexcept; // only valid when T is not an array type T * operator->() const noexcept; // only valid when T is not an array type // only valid when T is an array type element_type & operator[](std::ptrdiff_t i) const noexcept; element_type * get() const noexcept; bool unique() const noexcept; long use_count() const noexcept; explicit operator bool() const noexcept; void swap(shared_ptr & b) noexcept; template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const noexcept; template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const noexcept; }; template<class T, class U> bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept; template<class T, class U> bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept; template<class T, class U> bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept; template<class T> bool operator==(shared_ptr<T> const & p, std::nullptr_t) noexcept; template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & p) noexcept; template<class T> bool operator!=(shared_ptr<T> const & p, std::nullptr_t) noexcept; template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & p) noexcept; template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept; template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) noexcept; template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept; template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) noexcept; template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p); template<class D, class T> D * get_deleter(shared_ptr<T> const & p) noexcept; template<class T> bool atomic_is_lock_free( shared_ptr<T> const * p ) noexcept; template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept; template<class T> shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, int ) noexcept; template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept; template<class T> void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept; template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept; template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept; template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept; template<class T> bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, int, int ) noexcept; }
element_type
typedef ... element_type
當T不是數組類型時,element_type是類型T,當T是數組類型(U[]/U[N])時,element_type是類型U。
default constructor
constexpr shared_ptr() noexcept;
constexpr shared_ptr(std::nullptr_t) noexcept;
構造一個空的shared_ptr,其知足條件
use_count() == 0 && get() == 0
pointer constructor
template<class Y> explicit shared_ptr(Y* p);
類型Y必須是完整類型。當T是數組類型,表達式delete[] p;當T不是數組類型,表達式delete p必須是符合語法規則、符合定義並不會拋出異常的。當類型T是U[N],Y(*)[N]能夠轉換成T*;當類型T是U[],Y(*)[]能夠轉換成T*;除此以外Y*能夠轉換成T*。
當類型T不是數組類型,構造一個擁有p全部權的shared_ptr。除此以外構造一個擁有數組p全部權的shared_ptr,默認的刪除器是delete[] p。
use_count() == 1 && get() == p。若是類型T不是數組類型而且p能夠明確的轉換成enabled_shared_from_this<V>,p->shared_from_this()返回*this的副本。
內存不足時拋出std::bad_alloc或實現定義的異常。
異常安全,當T是數組類型,構造函數會調用delete[] p;當T不是數組類型,會調用delete p。
note:
p必須是0或者C++ new出來的指針類型。當p是0時,use_count()也是1,而且delete p也是不會報錯的。
這個構造函數會用模板記錄實際傳入的類型,析構函數會delete原始類型,即使T沒有虛析構函數或void類型。
template<class Y, class D> shared_ptr
(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class D> shared_ptr(std::nullptr_t p, D d);
template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
類型D必須是可拷貝構造的。D的構造和析構不能拋出異常。表達式delete p必須是符合語法規則、符合定義並不會拋出異常的。類型A必須是符合C++標準的內存配置器。當類型T是U[N],Y(*)[N]能夠轉換成T*;當類型T是U[],Y(*)[]能夠轉換成T*;除此以外Y*能夠轉換成T*。
構造一個擁有指針p全部權和刪除器d的shared_ptr對象。帶內存配置器的構造函數使用配置器a分配內存。
use_count() == 1 && get() == p。若是類型T不是數組類型而且p能夠明確的轉換成enabled_shared_from_this<V>,p->shared_from_this()返回*this的副本。
內存不足時拋出std::bad_alloc或實現定義的異常。
異常拋出時,會調用d(p)。
shared_ptr(shared_ptr const &r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> const &r) noexcept;
Y* 能夠隱式轉換成 T*。
若是 r 是空shared_ptr,則構造一個空shared_ptr;不然構造一個擁有r全部權的shared_ptr。
get() == r.get() && use_count() == r.use_count()
shared_ptr(shared_ptr const &&r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> const &&r) noexcept;
Y* 能夠隱式轉換成 T*。
移動構造一個shard_ptr.
新構造的shared_ptr接管r管理的內存。若是r是空對象,則r.get() == 0。
template<class Y> shared_ptr(shared_ptr<Y> const &r, element_type *p) noexcept;
構造一個shared_ptr對象,擁有r的全部權並存儲指針p。
get() == p && use_count() == r.use_count()。
template<class Y> shared_ptr(shared_ptr<Y> const &&r, element_type *p) noexcept;
移動構造一個shared_ptr對象,擁有r的全部權並存儲指針p。
get() == p && use_count() == r.use_count()。若是r是空對象,r.get() == 0。
template<class Y> explicit shared_ptr(weak_ptr<class Y> const& r);
Y* 能夠隱式轉換成 T*。
構造一個shared_ptr對象,擁有r的全部權並存儲r的指針副本。
use_count() == r.use_count()。
當 r.use_count() == 0 時,拋出異常bad_weak_ptr
若是拋出異常,那麼構造函數沒有起做用。
template<class Y> shared_ptr(auto_ptr<class Y> const& r);
template<class Y> shared_ptr(auto_ptr<class Y> const&& r);
Y* 能夠隱式轉換成 T*。
構造一個shared_ptr對象,存儲r.release()
use_count() == 1。
當內存資源不足時,拋出異常std::bad_alloc或實現定義的異常。
若是拋出異常,那麼構造函數沒有起做用。
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
Y* 能夠隱式轉換成 T*。
當內存資源不足時,拋出異常std::bad_alloc或實現定義的異常。
若是拋出異常,那麼構造函數沒有起做用。
~shared_ptr() noexcept;
-空shared_ptr,或者use_count() > 1,什麼也不作
shared_ptr& operator=(shared_ptr const& r) noexcept;
template<class Y> shared_ptr& operator=(shared_ptr<Y> const& r) noexcept;
template<class Y> shared_ptr& operator=(std::auto_ptr<Y> const& r);
至關於 shared_ptr(r).swap(*this)
返回*this
shared_ptr& operator=(shared_ptr && r) noexcept;
template<class Y> shared_ptr& operator=(shared_ptr<Y> && r) noexcept;
template<class Y> shared_ptr& operator=(std::auto_ptr<Y> && r);
template<class Y, class D> shared_ptr& operator=(std::unique_ptr<Y, D> && r);
至關於 shared_ptr(std::move(r)).swap(*this)
返回*this
shared_ptr& operator=(std::nullptr_t) noexcept;
至關於 shared_ptr().swap(*this)
返回*this
void reset() noexcept;
至關於 shared_ptr().swap(*this)
template<class Y> void reset(Y * p);
至關於 shared_ptr(p).swap(*this)
template<class Y, class D> void reset(Y * p, D d);
至關於 shared_ptr(p, d).swap(*this)
template<class Y, class D, class A> void reset(Y * p, D d, A a);
至關於 shared_ptr(p, d, a).swap(*this)
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p) noexcept;
至關於 shared_ptr(r, p).swap(*this)
template<class Y> void reset(shared_ptr<Y> && r, element_type * p) noexcept;
至關於 shared_ptr(std::move(r), p).swap(*this)
T & operator*() const noexcept;
類型T不是數組類型。get() != 0
返回 *get()
T * operator->() const noexcept;
類型T不是數組類型。get() != 0
返回 get()
類型T是數組類型。get() != 0。若是T是T[U],那麼i < N
返回 get()[i]
element_type * get() const noexcept;
返回shared_ptr存儲的指針
bool unique() const noexcept;
返回 use_count() == 1
long use_count() const noexcept;
若是存儲指針爲空返回0,否正返回持有該指針地址的shared_ptr數量
explicit operator bool() const noexcept;
返回 get() != 0
void swap(shared_ptr & b) noexcept;
交換兩個智能指針的保存的指針
template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const noexcept;
template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const noexcept;
詳見 operator< 的解釋
template<class T, class D> bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
返回 a.get() == b.get()
template<class T, class D> bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
返回 a.get() != b.get()
template<class T> bool operator==(shared_ptr<T> const & a, std::nullptr_t) noexcept;
template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & a) noexcept;
返回 a.get() == 0
template<class T> bool operator!=(shared_ptr<T> const & a, std::nullptr_t) noexcept;
template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & a) noexcept;
返回 a.get() != 0
template<class T, class D> bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
未明確的排序規則
在C++標準中,operator< 是一種嚴格的弱排序
兩個shared_ptr對象都爲空,或者知足!(a < b) && !(b < a),那麼兩個智能指針相等
shared_ptr對象能夠做爲關聯容器的key,其他的比較操做符都是被忽略的。
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;
a.swap(b)
template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) noexcept;
p.get()