中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++11中weak_ptr的詳細解析

發布時間:2020-07-17 15:26:45 來源:億速云 閱讀:271 作者:小豬 欄目:編程語言

這篇文章主要講解了C++11中weak_ptr的詳細解析,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。

1、為什么需要weak_ptr?

在正式介紹weak_ptr之前,我們先來回憶一下shared_ptr的一些知識。

我們知道shared_ptr是采用引用計數的智能指針,多個shared_ptr實例可以指向同一個動態對象,并維護了一個共享的引用計數器。

對于引用計數法實現的計數,總是避免不了循環引用(或環形引用)的問題,shared_ptr也不例外。

我們先來看看下面這個例子:

#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;
 // 函數結束,思考一下:spa和spb會釋放資源么?
}

上面代碼的輸出如下:

ClassA Constructor...
ClassB Constructor...
Program ended with exit code: 0

從上面代碼中,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 的引用計數值。

示例:

int main() {
 shared_ptr<int> sp(new int(5));
 cout << "創建前sp的引用計數:" << sp.use_count() << endl; // use_count = 1

 weak_ptr<int> wp(sp);
 cout << "創建后sp的引用計數:" << sp.use_count() << endl; // use_count = 1
}

3.2如何判斷weak_ptr指向對象是否存在

既然weak_ptr并不改變其所共享的shared_ptr實例的引用計數,那就可能存在weak_ptr指向的對象被釋放掉這種情況。

這時,我們就不能使用weak_ptr直接訪問對象。那么我們如何判斷weak_ptr指向對象是否存在呢?

C++中提供了lock函數來實現該功能。

如果對象存在,lock()函數返回一個指向共享對象的shared_ptr,否則返回一個空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指向對象為空" << endl;
 }
}

試試把sp.reset()這行的注釋去掉看看結果有什么不同。

除此之外,weak_ptr還提供了expired()函數來判斷所指對象是否已經被銷毀。

示例:

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(); // 此時sp被銷毀
 cout << wp.expired() << endl; // true表示已被銷毀,否則為false
}

代碼輸入如下:

A Constructor...
A Destructor...
1

3.3如何使用weak_ptr

weak_ptr并沒有重載 operator->和 operator *操作符,因此不可直接通過weak_ptr使用對象,典型的用法是調用其lock函數來獲得shared_ptr示例,進而訪問原始對象。

最后,我們來看看如何使用weak_ptr來改造最前面的代碼,打破循環引用問題。

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;
 // 函數結束,思考一下:spa和spb會釋放資源么?
}

輸出結果如下:

ClassA Constructor...
ClassB Constructor...
ClassA Destructor...
ClassB Destructor...
Program ended with exit code: 0

從運行結果可以看到spa和spb指向的對象都得到釋放!

看完上述內容,是不是對C++11中weak_ptr的詳細解析有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西吉县| 汉川市| 永丰县| 翁源县| 海口市| 象山县| 嘉峪关市| 新宁县| 龙江县| 汉阴县| 乳山市| 墨脱县| 平泉县| 济阳县| 府谷县| 西藏| 射阳县| 肇庆市| 营山县| 外汇| 余姚市| 克东县| 无锡市| 焦作市| 福清市| 冀州市| 民丰县| 梧州市| 罗定市| 吉林省| 左贡县| 襄城县| 同心县| 塔河县| 英吉沙县| 石阡县| 凤阳县| 通州区| 扶沟县| 隆子县| 太保市|