你好,C++(78)12.2.2 引用計數:shared_ptr為什麼這麼聰明?
想要搶先看後面的章節?打賞本文10元,即可獲得帶插圖全本下載地址!
打賞完成記得私信我哦 :p
12.2.2 引用計數:shared_ptr為什麼這麼聰明?
這裡大家一定會問,shared_ptr為什麼這麼聰明,能夠知道它所指向的內存資源還有沒有人在使用?從而可以在沒人使用的情況下自動釋放這塊內存資源。原因其實很簡單,就像我們想要知道哪些人欠我們的錢一樣,我們總是把欠我們錢的人記錄在一個小本本上。如果某個人欠了我們的錢,我們就把他記錄在小本本上,如果他還錢了,我們就把他從小本本上刪去。這樣,我們一看小本本就知道誰欠我的錢了。shared_ptr對它所指向的內存資源的管理也是同樣的道理,在它的背後也有一個記賬的小本本——引用計數。當新增一個shared_ptr對該資源進行管理時,也就是新增一個指向此資源的shared_ptr時,它就會將該內存資源的引用計數加1;反之,當減少一個shared_ptr對該資源進行管理時,就會將該內存資源的引用計數減1;如果該內存資源的引用計數變為0,則說明沒有任何指針對其進行管理,就自動調用delete操作符釋放這塊內存資源。例如,下面這段程序展示了引用計數的工作機制:
// shared_ptr定義在頭文件<memory>中
#include <memory>
#include <iostream>
using namespace std;
int main()
{
shared_ptr<int> spFirst( new int );
// 這時,只有spFirst這個指針指向這塊int類型的內存資源,
// 所以這時它的引用計數是1
cout<<"當前引用計數: "<<spFirst.use_count()<<endl;
{
// 創建另外一個shared_ptr,並用spFirst對其進行賦值,
// 讓它們指向同一塊內存資源
shared_ptr<int> spCopy = spFirst;
// 因為spFirst和spCopy都指向這一塊內存資源,
// 所以這一資源的引用計數增加為2
cout<<"當前引用計數: "<<spFirst.use_count()<<endl;
}
// 當超出spCopy的作用域,spCopy結束其生命周期,
// 這塊內存資源的引用計數減1而重新變為1 cout<<"當前引用計數: "<<spFirst.use_count()<<endl;
// 當程序最終結束執行返回,spFirst指針也結束其生命周期後,
// 從此沒有任何指針指向此內存資源,引用計數減為0,內存資源自動得到釋放
return 0;
}
從這段代碼的輸出中我們可以清楚地看到,一塊內存資源的引用計數,也就是指向這塊內存資源的shared_ptr的個數。在程序的一開始,我們用new操作符申請了一塊int類型的內存,然後用返回的內存地址作為shared_ptr的構造函數的參數創建了spFirst這個shared_ptr對象。這時只有spFirst指向這塊內存資源,所以用use_count()函數獲得的引用計數是1。當程序進入「{}」包圍形成的代碼塊之後,spFirst被賦值給了spCopy,這就意味著增加了一個shared_ptr指向這塊內存資源,所以它的引用計數從1 增加為2。當程序退出「{}」包圍形成的代碼塊,也就是退出spCopy的作用域之後,spCopy被銷毀。這時又只剩下spFirst指向這塊內存資源,所以它的引用計數也從2減為1。當main()函數執行完畢退出後,spFirst也被銷毀,這時就沒有shared_ptr指向這塊內存資源了,它的引用計數從1減為0。當一塊內存資源的引用計數減少為0時,則意味著沒有任何shared_ptr指向這塊內存資源,也就無法對其進行訪問。既然誰都無法再次訪問到這塊內存資源,那就表示它已經使用完畢,shared_ptr會使用delete操作符自動釋放這塊內存資源。 整個過程如下圖12-2所示: