http://blog.csdn.net/xiejingfa/article/details/50772571
原創作品,轉載請標明:http://blog.csdn.net/Xiejingfa/article/details/50772571
如題,我們今天要講的是C++11引入的三種智能指針中的最后一個:weak_ptr。在學習weak_ptr之前最好對shared_ptr有所了解。如果你還不知道shared_ptr是何物,可以看看我的另一篇文章【C++11新特性】 C++11智能指針之shared_ptr。
1、為什么需要weak_ptr?
在正式介紹weak_ptr之前,我們先來回憶一下shared_ptr的一些知識。我們知道shared_ptr是采用引用計數的智能指針,多個shared_ptr實例可以指向同一個動態對象,并維護了一個共享的引用計數器。對于引用計數法實現的計數,總是避免不了循環引用(或環形引用)的問題,shared_ptr也不例外。
我們先來看看下面這個例子:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
上面代碼的輸出如下:
- 1
- 2
- 3
從上面代碼中,ClassA和ClassB間存在著循環引用,從運行結果中我們可以看到:當main函數運行結束后,spa和spb管理的動態資源并沒有得到釋放,產生了內存泄露。
為了解決類似這樣的問題,C++11引入了weak_ptr,來打破這種循環引用。
2、weak_ptr是什么?
weak_ptr是為了配合shared_ptr而引入的一種智能指針,它指向一個由shared_ptr管理的對象而不影響所指對象的生命周期,也就是將一個weak_ptr綁定到一個shared_ptr不會改變shared_ptr的引用計數。不論是否有weak_ptr指向,一旦最后一個指向對象的shared_ptr被銷毀,對象就會被釋放。從這個角度看,weak_ptr更像是shared_ptr的一個助手而不是智能指針。
3、weak_ptr如何使用?
接下來,我們來看看weak_ptr的簡單用法。
3.1如何創建weak_ptr實例
當我們創建一個weak_ptr時,需要用一個shared_ptr實例來初始化weak_ptr,由于是弱共享,weak_ptr的創建并不會影響shared_ptr的引用計數值。
示例:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
3.2如何判斷weak_ptr指向對象是否存在
既然weak_ptr并不改變其所共享的shared_ptr實例的引用計數,那就可能存在weak_ptr指向的對象被釋放掉這種情況。這時,我們就不能使用weak_ptr直接訪問對象。那么我們如何判斷weak_ptr指向對象是否存在呢?C++中提供了lock函數來實現該功能。如果對象存在,lock()函數返回一個指向共享對象的shared_ptr,否則返回一個空shared_ptr。
示例:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
試試把sp.reset()這行的注釋去掉看看結果有什么不同。
除此之外,weak_ptr還提供了expired()函數來判斷所指對象是否已經被銷毀。
示例:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
代碼輸入如下:
- 1
- 2
- 3
3.3如何使用weak_ptr
weak_ptr并沒有重載operator->和operator *操作符,因此不可直接通過weak_ptr使用對象,典型的用法是調用其lock函數來獲得shared_ptr示例,進而訪問原始對象。
最后,我們來看看如何使用weak_ptr來改造最前面的代碼,打破循環引用問題。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
輸出結果如下:
- 1
- 2
- 3
- 4
- 5
從運行結果可以看到spa和spb指向的對象都得到釋放!