c 智慧型指標 shared ptr

2021-08-18 13:46:59 字數 4760 閱讀 3466

為了更容易更方便的使用動態記憶體,c++提供了兩種智慧型指標shared_ptr和unique_ptr來管理動態物件,智慧型指標負責自動釋放所管理的物件,避免因為不合適的釋放導致的記憶體洩露和訪問已釋放記憶體的bug;

智慧型指標也是模板,建立乙個智慧型指標時,必須提供額外的型別資訊,如shared_ptr p1;

智慧型指標的使用方式和普通指標類似,解引用乙個智慧型指標返回它指向的物件,也可以在乙個條件判斷中使用智慧型指標,判斷它是否為空;

shared_ptr和unique_ptr都支援的操作:

shared_ptrsp;

unique_ptrup; 空智能指標,可以指向型別為t的物件

p 將p作為乙個條件判斷,若p不為空則為true

*p 解引用p,獲取它指向的物件

p.get() 返回p中儲存的指標。要小心使用,若智慧型指標釋放了物件,返回的指標指向的物件也就消失了

swap(p,q)

p.swap(q) 交換p和q中的指標

shared_ptr獨有的操作:

make_shared(args)             返回乙個shared_ptr,指向乙個動態分配的型別為t的物件,使用引數args初始化此物件

shared_ptrp(q) p是shared_ptr的拷貝;此操作會遞增q中的計數器。q中的指標必須能夠轉換為t^*

p = q p和q都是shared_ptr,所儲存的指標必須能夠相互轉換。此操作會遞減p的引用計數, 同時遞增q的引用計數;若p的引用計數遞減後變為0,則將其管理的原記憶體釋放

p.unique() 若p.use_count() == 1,返回true,表示對p所指向的記憶體只有乙份引用計數,否則返回false

p.use_count() 返回與p共享物件的智慧型指標數量。可能很慢,主要用於除錯

shared_ptr允許多個指標指向同乙個物件;

最安全的分配和使用動態記憶體的方法是呼叫std::make_shared函式,該函式在動態記憶體中分配乙個物件並初始化它,返回指向此物件的shared_ptr。函式標頭檔案 #include

make_ptr用其引數來構造給定型別的物件,但必須要求傳遞的引數與t的某個建構函式可以匹配;

shared_ptr p3 = make_shared(43);

shared_ptr p4 = make_shared(10,』9』);//p4指向」9999999999」

shared_ptr p5 = make_shared();//p5指向乙個值初始化的int,即指向乙個值為0的int

通常使用auto定義乙個物件來儲存make_shared的結果,如

auto p6 = make_shared

使用內建指標初始化shared_ptr的建構函式是explicit的,不允許隱式進行轉換,必須使用直接初始化的形式。

shared_ptr p1 = new int(42);//錯誤,必須使用直接初始化形式

shared_ptr p2(new int(42));//正確,使用了直接初始化形式

shared_ptr clone(int p)

但是由於下面所述的更多的原因,不建議混合使用普通指標和shared_ptr,所以還是建議使用make_shared函式分配和使用動態記憶體。

每個shared_ptr都有乙個關聯的計數器,稱之為引用計數;

當用乙個shared_ptr初始化另乙個shared_ptr、將其作為引數傳遞給另乙個引數、將shared_ptr作為返回值時,它所關聯的引用計數都會增加;

當給shared_ptr賦予乙個新值、shared_ptr被銷毀、區域性shared_ptr物件離開作用域,它所關聯的引用計數都會遞減;

shared_ptr的析構函式會遞減它所指向的物件的引用計數,如果引用計數變為0,則shared_ptr的析構函式會銷毀物件並釋放物件所占用的記憶體。

當和shared_ptr關聯的動態物件的引用計數變為0時,shared_ptr會自動呼叫該動態物件的析構函式或指定函式釋放動態物件占用的記憶體。這種特性會使得動態記憶體的管理更加方便,不易出現記憶體洩露和重複delete的bug。

shared_ptr在無用之後仍然被保留的一種情況是:將shared_ptr放入了容器中,而後不再需要全部的元素,那麼要求對不需要的元素顯式進行erase操作,否則還是會造成記憶體洩露。

預設情況下,乙個用來初始化智慧型指標的普通指標必須指向動態記憶體,因為智慧型指標預設使用delete釋放它關聯的物件。

可以將智慧型指標繫結到乙個指向其他型別資源的指標上,但這樣做的時候,需要自己提供函式來替換delete。

定義和改變shared_ptr的其他方法:

shared_ptrp(q)    智慧型指標p管理普通指標q指向的物件,但要求q必須指向new分配的記憶體,且可以轉換為t的指標

shared_ptrp(u) p從unique_ptr那裡接管了物件的所有權,且將u置為空

shared_ptrp(q,d) p接管了內建指標q所指向的物件的所有權,q必須轉換為t的指標。p將使用可呼叫物件d來代替delete

sharedp(p2,d) p是shared_ptr q的拷貝,唯一的區別是p將用可呼叫物件d來代替delete

p.reset();p.reset(q);p.reset(q,d) 若p是唯一指向物件的shared_ptr,reset會釋放此物件;若傳遞了可選引數q,則會令p指向q,否則會將p置為空;若還傳遞了引數d,將會呼叫d而不是delete來釋放q

shared_ptr可以協調物件的析構,但這僅限於其自身的拷貝(也是shared_ptr)之間,但如果混用了智慧型指標與普通指標,則有發生bug的風險。

void process(shared_ptr ptr)

//ptr離開作用域,被銷毀

shared_ptr p(new int(42));//引用計數為1

process(p);//由於process函式的形參為值傳遞方式,所以在函式內部時,處理的是p的副本,對p進行了複製,那麼在process函式內部的引用計數為2,一旦函式結束,內部的副本被銷毀,引用計數變為1,不影響正常的資料訪問

int j = *p;//正確

int *x(new int(42));

process(x);//錯誤,不允許隱式轉換

process(shared_ptr p(x));//可以正確呼叫,但是一旦函式指向結束,臨時物件會被釋放,此時引用計數變為0,所指向的物件的記憶體會被釋放

int j = *x;//錯誤,會發生未定義的行為,因為x此時是乙個空懸指標

當將乙個shared_ptr繫結到乙個普通指標時,我們就將記憶體管理的責任交給了shared_ptr。一旦這樣做了之後,就不應該再用內建指標來訪問shared_ptr所指向的記憶體了。

智慧型指標有乙個get函式,獲取智慧型指標管理的物件的內建指標。這個函式設計的初衷是為了呼叫不能以智慧型指標為引數的函式。

但必須注意的是:使用get函式返回的指標的**不能delete此指標,特別是,永遠不要用get初始化另乙個智慧型指標或為另乙個智慧型指標賦值。

shared_ptr p(new int(42));

int *q = p.get();

//程式結束時,p1被銷毀,它所指向的記憶體也被釋放

int j = *p;//未定義的行為,因為此時p指向的記憶體已經被釋放了

p.reset(new int(1024));//p指向了新的物件

reset經常和unique一起使用,在控制多個shared_ptr共享的物件。在改變底層物件之前,要檢查是否我們未當前物件僅有的使用者,如果不是的話,在改變之前需要製作乙份新的拷貝。

if(! p.unique())

*p += n;

**發生異常的時候,中間退出,那麼對於new出來的物件如果沒有顯式釋放的話就造成了記憶體洩露。可以用智慧型指標避免這一現象。

void f()

//函式結束時,sp會被析構,物件的引用計數減1變為0,自動釋放物件所占用的記憶體

預設情況下,shared_ptr認為指向動態記憶體,且shared_ptr釋放時會呼叫它管理的指標的delete操作。

但如果shared_ptr管理的是自定義型別,且該型別沒有良好設計的建構函式時,那麼使用shared_ptr依然會造成記憶體洩露,這種情況下可以定義乙個其他的函式來代替delete操作。

void mydelete

void f()

//函式結束或者發生異常時,會析構p,此時會呼叫mydelete函式釋放記憶體

如果智慧型指標管理的不是new出來的物件,那麼需要自己定義乙個刪除器。

void mydelete

void f(input& d)

//函式結束或者發生異常時,會析構p,此時會呼叫mydelete函式進行指定的操作

智慧型指標可以提供對動態分配的記憶體安全而又方便的管理,但這是建立在正確使用的前提下的。為了正確使用智慧型指標,必須堅持一些基本原則:

程式使用動態記憶體是出於下述三種原因之一:

1.程式不知道自己需要使用多少物件;這種原因的使得出現了容器

2.程式不知道所需物件的準確型別;暫時不知道

3.程式需要在多個物件間共享資料;這種原因造成了shared_ptr

C 智慧型指標 shared ptr

shared ptr 是乙個標準的共享所有權的智慧型指標,允許多個指標指向同乙個物件.定義在 memory 檔案中 非memory.h 命名空間為 std.shared ptr 是為了解決 auto ptr 在物件所有權上的侷限性 auto ptr 是獨佔的 在使用引用計數的機制上提供了可以共享所有...

shared ptr智慧型指標

智慧型指標是乙個行為類似指標的物件。我們在使用堆記憶體時,都需要及時地進行釋放,避免造成記憶體洩漏。但我們偶爾也會忘記將其釋放掉,從而造成記憶體洩漏。並且,在釋放的時候,我們可能對某乙個指標進行了重複釋放,導致程式崩潰的問題。為了能夠解決這些問題,從而有了智慧型指標的設計。智慧型指標一共有四種,分別...

shared ptr(智慧型指標)

只要將 new 運算子返回的指標 p 交給乙個 shared ptr 物件 託管 就不必擔心在 寫delete p語句 實際上根本不需要編寫這條語句,託管 p 的 shared ptr 物件在消亡時會自動執行delete p。而且,該 shared ptr 物件能像指標 p 樣使用,即假設託管 p ...