【C++11新特性】 C++11智能指针之weak_ptr
http://blog.csdn.net/xiejingfa/article/details/50772571
原創(chuàng)作品,轉(zhuǎn)載請(qǐng)標(biāo)明:http://blog.csdn.net/Xiejingfa/article/details/50772571
如題,我們今天要講的是C++11引入的三種智能指針中的最后一個(gè):weak_ptr。在學(xué)習(xí)weak_ptr之前最好對(duì)shared_ptr有所了解。如果你還不知道shared_ptr是何物,可以看看我的另一篇文章【C++11新特性】 C++11智能指針之shared_ptr。
1、為什么需要weak_ptr?
在正式介紹weak_ptr之前,我們先來(lái)回憶一下shared_ptr的一些知識(shí)。我們知道shared_ptr是采用引用計(jì)數(shù)的智能指針,多個(gè)shared_ptr實(shí)例可以指向同一個(gè)動(dòng)態(tài)對(duì)象,并維護(hù)了一個(gè)共享的引用計(jì)數(shù)器。對(duì)于引用計(jì)數(shù)法實(shí)現(xiàn)的計(jì)數(shù),總是避免不了循環(huán)引用(或環(huán)形引用)的問(wèn)題,shared_ptr也不例外。
我們先來(lái)看看下面這個(gè)例子:
#include <iostream> #include <memory> #include <vector> using namespace std;class ClassB;class ClassA { public:ClassA() { cout << "ClassA Constructor..." << endl; }~ClassA() { cout << "ClassA Destructor..." << endl; }shared_ptr<ClassB> pb; // 在A中引用B };class ClassB { public:ClassB() { cout << "ClassB Constructor..." << endl; }~ClassB() { cout << "ClassB Destructor..." << endl; }shared_ptr<ClassA> pa; // 在B中引用A };int main() {shared_ptr<ClassA> spa = make_shared<ClassA>();shared_ptr<ClassB> spb = make_shared<ClassB>();spa->pb = spb;spb->pa = spa;// 函數(shù)結(jié)束,思考一下:spa和spb會(huì)釋放資源么? }- 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
上面代碼的輸出如下:
ClassA Constructor... ClassB Constructor... Program ended with exit code: 0- 1
- 2
- 3
從上面代碼中,ClassA和ClassB間存在著循環(huán)引用,從運(yùn)行結(jié)果中我們可以看到:當(dāng)main函數(shù)運(yùn)行結(jié)束后,spa和spb管理的動(dòng)態(tài)資源并沒(méi)有得到釋放,產(chǎn)生了內(nèi)存泄露。
為了解決類(lèi)似這樣的問(wèn)題,C++11引入了weak_ptr,來(lái)打破這種循環(huán)引用。
2、weak_ptr是什么?
weak_ptr是為了配合shared_ptr而引入的一種智能指針,它指向一個(gè)由shared_ptr管理的對(duì)象而不影響所指對(duì)象的生命周期,也就是將一個(gè)weak_ptr綁定到一個(gè)shared_ptr不會(huì)改變shared_ptr的引用計(jì)數(shù)。不論是否有weak_ptr指向,一旦最后一個(gè)指向?qū)ο蟮膕hared_ptr被銷(xiāo)毀,對(duì)象就會(huì)被釋放。從這個(gè)角度看,weak_ptr更像是shared_ptr的一個(gè)助手而不是智能指針。
3、weak_ptr如何使用?
接下來(lái),我們來(lái)看看weak_ptr的簡(jiǎn)單用法。
3.1如何創(chuàng)建weak_ptr實(shí)例
當(dāng)我們創(chuàng)建一個(gè)weak_ptr時(shí),需要用一個(gè)shared_ptr實(shí)例來(lái)初始化weak_ptr,由于是弱共享,weak_ptr的創(chuàng)建并不會(huì)影響shared_ptr的引用計(jì)數(shù)值。
示例:
int main() {shared_ptr<int> sp(new int(5));cout << "創(chuàng)建前sp的引用計(jì)數(shù):" << sp.use_count() << endl; // use_count = 1weak_ptr<int> wp(sp);cout << "創(chuàng)建后sp的引用計(jì)數(shù):" << sp.use_count() << endl; // use_count = 1 }- 1
- 2
- 3
- 4
- 5
- 6
- 7
3.2如何判斷weak_ptr指向?qū)ο笫欠翊嬖?/strong>
既然weak_ptr并不改變其所共享的shared_ptr實(shí)例的引用計(jì)數(shù),那就可能存在weak_ptr指向的對(duì)象被釋放掉這種情況。這時(shí),我們就不能使用weak_ptr直接訪問(wèn)對(duì)象。那么我們?nèi)绾闻袛鄔eak_ptr指向?qū)ο笫欠翊嬖谀?#xff1f;C++中提供了lock函數(shù)來(lái)實(shí)現(xiàn)該功能。如果對(duì)象存在,lock()函數(shù)返回一個(gè)指向共享對(duì)象的shared_ptr,否則返回一個(gè)空shared_ptr。
示例:
class A { public:A() : a(3) { cout << "A Constructor..." << endl; }~A() { cout << "A Destructor..." << endl; }int a; };int main() {shared_ptr<A> sp(new A());weak_ptr<A> wp(sp);//sp.reset();if (shared_ptr<A> pa = wp.lock()){cout << pa->a << endl;}else{cout << "wp指向?qū)ο鬄榭?#34; << endl;} }- 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()這行的注釋去掉看看結(jié)果有什么不同。
除此之外,weak_ptr還提供了expired()函數(shù)來(lái)判斷所指對(duì)象是否已經(jīng)被銷(xiāo)毀。
示例:
class A { public:A() : a(3) { cout << "A Constructor..." << endl; }~A() { cout << "A Destructor..." << endl; }int a; };int main() {shared_ptr<A> sp(new A());weak_ptr<A> wp(sp);sp.reset(); // 此時(shí)sp被銷(xiāo)毀cout << wp.expired() << endl; // true表示已被銷(xiāo)毀,否則為false }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
代碼輸入如下:
A Constructor... A Destructor... 1- 1
- 2
- 3
3.3如何使用weak_ptr
weak_ptr并沒(méi)有重載operator->和operator *操作符,因此不可直接通過(guò)weak_ptr使用對(duì)象,典型的用法是調(diào)用其lock函數(shù)來(lái)獲得shared_ptr示例,進(jìn)而訪問(wèn)原始對(duì)象。
最后,我們來(lái)看看如何使用weak_ptr來(lái)改造最前面的代碼,打破循環(huán)引用問(wèn)題。
class ClassB;class ClassA { public:ClassA() { cout << "ClassA Constructor..." << endl; }~ClassA() { cout << "ClassA Destructor..." << endl; }weak_ptr<ClassB> pb; // 在A中引用B };class ClassB { public:ClassB() { cout << "ClassB Constructor..." << endl; }~ClassB() { cout << "ClassB Destructor..." << endl; }weak_ptr<ClassA> pa; // 在B中引用A };int main() {shared_ptr<ClassA> spa = make_shared<ClassA>();shared_ptr<ClassB> spb = make_shared<ClassB>();spa->pb = spb;spb->pa = spa;// 函數(shù)結(jié)束,思考一下:spa和spb會(huì)釋放資源么? }- 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
輸出結(jié)果如下:
ClassA Constructor... ClassB Constructor... ClassA Destructor... ClassB Destructor... Program ended with exit code: 0- 1
- 2
- 3
- 4
- 5
從運(yùn)行結(jié)果可以看到spa和spb指向的對(duì)象都得到釋放!
總結(jié)
以上是生活随笔為你收集整理的【C++11新特性】 C++11智能指针之weak_ptr的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 小米盒子4与小米盒子3增强版哪个好用?
- 下一篇: 【C++11新特性】 C++11智能指针