天天看點

C++11中的智能指針

在c++11中,引入了智能指針。主要有:unique_ptr, shared_ptr, weak_ptr。

這3種指針元件就是采用了boost裡的智能指針方案。很多有用過boost智能指針的朋友,很容易地就能發現它們之間的關間:

unique_ptr

scoped_ptr

獨占指針對象,并保證指針所指對象生命周期與其一緻

shared_ptr

可共享指針對象,可以指派給shared_ptr或weak_ptr。

指針所指對象在所有的相關聯的shared_ptr生命周期結束時結束,是強引用。

weak_ptr

它不能決定所指對象的生命周期,引用所指對象時,需要lock()成shared_ptr才能使用。

c++11将boost裡的這一套納入了标準。

如下為示例代碼:

[1]: <code>unique_ptr</code> 是禁止複制指派的,始終保持一個 <code>unique_ptr</code> 管理一個對象。

[2]: <code>unique_ptr</code> 雖然不能指派,但可以通過 <code>move()</code> 函數轉移對象的所有權。一旦被 <code>move()</code> 了,原來的 <code>up1</code> 則不再有效了。

[3]: <code>reset()</code> 可以讓 <code>unique_ptr</code> 提前釋放指針。

[4]: 由 <code>shared_ptr</code> 構造一個 <code>weak_ptr</code>。

如下面的示例:

在記憶體中:

C++11中的智能指針

s1, s2, w1 都指向一個 ptr_manage 的對象。

在該對象中有 <code>shared_ref_count</code> 與 <code>weak_ref_count</code> 兩個域分别記錄引用它的 <code>shared_ptr</code> 與 <code>weak_ptr</code> 的個數。這個很容易辦到,隻要在複制構造與指派函數中對相當地引用值進行加1,在析構中減1即可。<code>ptr_manage</code> 中的 <code>ptr</code> 域存放真正的對象指針位址。

當 <code>shared_ref_cnt</code> 被減為0時,自動釋放 <code>ptr</code> 指針所指向的對象。當 <code>shared_ref_cnt</code> 與 <code>weak_ref_cnt</code> 都變成0時,才釋放 <code>ptr_manage</code> 對象。

如此以來,隻要有相關聯的 <code>shared_ptr</code> 存在,對象就存在。<code>weak_ptr</code> 不影響對象的生命周期。當用 <code>weak_ptr</code> 通路對象時,對象有可能已被釋放了,要先 <code>lock()</code>。

當執行:

此時: 

C++11中的智能指針

<code>shared_ref_cnt</code> 由2減成了1。

再執行:

此時:

C++11中的智能指針

<code>shared_ref_cnt</code> 已被減到0了,<code>ptr</code> 所對應的object已被釋放,<code>ptr</code> 被清0。此時,<code>ptr_manage</code> 依舊保留。因為 <code>w1</code> 還需要引用它。

在最後,<code>w1</code> 也析構了的時候:

C++11中的智能指針

<code>ptr_manage</code> 中的 <code>weak_ref_cnt</code> 被減成0,最後連 <code>ptr_manage</code> 都釋放了。