C 的智慧型指標之shared ptr

2021-08-22 12:15:09 字數 4177 閱讀 3814

shared_ptr 是乙個標準的共享所有權的智慧型指標, 允許多個指標指向同乙個物件. 定義在 memory 檔案中(非memory.h), 命名空間為 std.

shared_ptr 是為了解決 auto_ptr 在物件所有權上的侷限性(auto_ptr 是獨佔的), 在使用引用計數的機制上提供了可以共享所有權的智慧型指標, 當然這需要額外的開銷:

(1) shared_ptr 物件除了包括乙個所擁有物件的指標外, 還必須包括乙個引用計數**物件的指標.

(2) 時間上的開銷主要在初始化和拷貝操作上, *和->操作符過載的開銷跟auto_ptr是一樣.

(3) 開銷並不是我們不使用shared_ptr的理由, 永遠不要進行不成熟的優化, 直到效能分析器告訴你這一點.

可以使用模板函式 make_shared 建立物件, make_shared 需指定型別(『<>』中)及引數(『()』內), 傳遞的引數必須與指定的型別的建構函式匹配. 如:

std:

:shared_ptr sp1 = std:

:make_shared(10);

std:

:shared_ptr:

:string> sp2 = std:

:make_shared:

:string>("hello c++");

也可以定義 auto 型別的變數來儲存 make_shared 的結果.

auto sp3 = std:

:make_shared(11);

printf("sp3=%d\n", *sp3);

auto sp4 = std:

:make_shared:

:string>("c++11");

printf("sp4=%s\n", (*sp4).c_str());

use_count 返回引用計數的個數

unique 返回是否是獨佔所有權( use_count 為 1)

swap 交換兩個 shared_ptr 物件(即交換所擁有的物件)

reset 放棄內部物件的所有權或擁有物件的變更, 會引起原有物件的引用計數的減少

get 返回內部物件(指標), 由於已經過載了()方法, 因此和直接使用物件是一樣的.如 shared_ptr sp(new int(1)); sp 與 sp.get()是等價的

以下**演示各個函式的用法與特點:

std::shared_ptr

sp0(new

int(2));

std::shared_ptr

sp1(new

int(11));

std::shared_ptr

sp2 = sp1;

printf("%d\n", *sp0); // 2

printf("%d\n", *sp1); // 11

printf("%d\n", *sp2); // 11

sp1.swap(sp0);

printf("%d\n", *sp0); // 11

printf("%d\n", *sp1); // 2

printf("%d\n", *sp2); // 11

std::shared_ptr

sp3(new

int(22));

std::shared_ptr

sp4 = sp3;

printf("%d\n", *sp3); // 22

printf("%d\n", *sp4); // 22

sp3.reset();

printf("%d\n", sp3.use_count()); // 0

printf("%d\n", sp4.use_count()); // 1

printf("%d\n", sp3); // 0

printf("%d\n", sp4); // 指向所擁有物件的位址

std::shared_ptr

sp5(new

int(22));

std::shared_ptr

sp6 = sp5;

std::shared_ptr

sp7 = sp5;

printf("%d\n", *sp5); // 22

printf("%d\n", *sp6); // 22

printf("%d\n", *sp7); // 22

printf("%d\n", sp5.use_count()); // 3

printf("%d\n", sp6.use_count()); // 3

printf("%d\n", sp7.use_count()); // 3

sp5.reset(new

int(33));

printf("%d\n", sp5.use_count()); // 1

printf("%d\n", sp6.use_count()); // 2

printf("%d\n", sp7.use_count()); // 2

printf("%d\n", *sp5); // 33

printf("%d\n", *sp6); // 22

printf("%d\n", *sp7); // 22

std::shared_ptr

sp1 = std::make_shared(10);

std::shared_ptr

sp2 = std::make_shared(11);

auto sp3 = sp2; 或 auto sp3(sp2);

printf("sp1.use_count = %d\n", sp1.use_count()); // 1

printf("sp2.use_count = %d\n", sp2.use_count()); // 2

printf("sp3.use_count = %d\n", sp3.use_count()); // 2

sp3 = sp1;

printf("sp1.use_count = %d\n", sp1.use_count()); // 2

printf("sp2.use_count = %d\n", sp2.use_count()); // 1

printf("sp3.use_count = %d\n", sp3.use_count()); // 2

(1) 程式不知道自己需要使用多少物件. 如使用視窗類, 使用 shared_ptr 為了讓多個物件能共享相同的底層資料.

(2) 程式不知道所需物件的準確型別.

(3) 程式需要在多個物件間共享資料.

(1) 禁止純指標給智慧型指標賦值或者拷貝構造。

int* a=new

int(2);

shared_ptr

sp=a;// error

sp=a;// error

(2)shared_ptr多次引用同一資料,會導致兩次釋放同一記憶體。如下:

(3)使用share_ptr造成迴圈引用

#include

using

namespace

std;

struct node

int data;

};void funtest()

int main()

當出現上述問題時,有以下3種解決方法:

1️⃣當只剩下最後乙個引用的時候需要手動打破迴圈引用釋放物件。

2️⃣當parent的生存期超過children的生存期的時候,children改為使用乙個普通指標指向parent。

3️⃣使用弱引用的智慧型指標(weak_ptr)打破這種迴圈引用。雖然這三種方法都可行,但方法1和方法2都需要程式設計師手動控制。

boost的指標智慧型指標(shared ptr)

boost智慧型指標常用的函式 get 獲取原始指標 bool unique 檢測是否唯一 long use count 引用計數 void swap 交換指標 reset 將引用計數減1,停止對指標的共享,除非引用計數為0,否則不會發生刪除操作。shared ptrspi new int 乙個in...

智慧型指標 auto ptr與shared ptr

auto ptr auto ptr是當年c 標準庫中提供的一種智慧型指標。auto ptr在構造時獲取某個物件的所有權,在析構時釋放該物件。可以提高 的安全性。例如 int p new int 0 auto ptrap p auto ptr主要是解決被異常丟擲時發生資源洩露問題。注意 1 auto ...

C 之智慧型指標

本文發表於1999年10月份的c c users journal,17 10 1.為什麼稱它為 自動 指標?auto ptr只是眾多可能的智慧型指標之一。許多商業庫提供了更複雜的智慧型指標,用途廣泛而令人驚異,從管理引用的數量到提供先進的 服務。可以把標準c auto ptr看作智慧型指標的ford...