c 智慧型指標

2021-08-31 13:40:10 字數 2866 閱讀 6023

靜態記憶體和棧記憶體。靜態記憶體用來儲存區域性的static物件、類的static資料成員以及定義在任何函式之外的變數。棧記憶體用來儲存定義在函式內的非static的物件。分配在靜態或者棧記憶體中的物件由編譯器自動建立和銷毀。

對於棧物件,僅在其定義的程式執行時才存在;static物件在使用之前分配,在程式結束時銷毀。

除了靜態記憶體和棧記憶體之外,每個程式還擁有乙個記憶體池。這部分記憶體被稱作自由空間或堆。程式用堆來儲存動態分配的物件-即那些在程式執行時分配的物件。動態物件的生存週期由程式來控制,也就是程式不在使用時,我們**必須顯式的銷毀它。

但是動態物件的正確釋放被證明是程式設計中極其容易出錯的地方。為了更安全地使用動態物件,標準庫定義了兩個智慧型指標型別來動態管理動態分配的物件。當乙個物件應該被釋放時,指向它的智慧型指標可以確保自動的釋放它。

動態記憶體的管理是通過一對運算符號來完成的:new,在動態記憶體中為物件分配記憶體空間並返回乙個指向該物件的指標,我們可以選擇對物件進行初始化;delete,接受乙個動態物件的指標,銷毀該物件,並釋放與之關聯的記憶體。

為了更容易的使用動態記憶體,新的標準提出兩種智慧型指標:重要的區別是它負責自動釋放所指向的物件。

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

unique_ptr則獨佔所指向的物件。

標準庫還定義了乙個名為weak_ptr的伴隨類,它是乙個弱引用,指向shared_ptr所管理的物件。這三個型別都定義在memory標頭檔案中。

share_ptr p1; //shared_ptr,可以指向string

shared_ptrp2; // shared_ptr,可以指向int的list

預設初始化的智慧型指標中儲存著乙個空指標。

智慧型指標的使用方式與普通指標類似。解引用乙個智慧型指標返回指向的物件。如果乙個條件判斷中使用智慧型指標,效果就是檢測它是否為空。

if(p1&&p1->empty())  //如果p1不為空,檢測它是否指向乙個空的string

*p1 = "hi"; //如果p1指向乙個空的string,解引用p1,將乙個新值賦予string

share_ptr和unique_ptr都支援的操作

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

unique_ptrup

p 將用作乙個判斷條件,若p指向乙個物件,則為true

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

p->mem 等價於(*p).mem

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

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

p.swap(q)

make_share(args) 返回乙個share_ptr,指向乙個動態分配的型別為t的物件。使用args初始化此物件

share_ptrp (q) p是share_ptr q的拷貝;此操作會遞增q中的計數器,q中的指標必須能轉換為t*

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

p.unique() 若p.use_count()為1,返回true;否則返回false。

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

make_share函式

最安全的分配和使用動態記憶體的方法是呼叫乙個名為make_shared的標準庫函式。此函式在動態記憶體中分配乙個物件並初始化它,返回指向此物件的share_ptr。與智慧型指標一樣,make_shared也定義在標頭檔案memory中。

make_share t引數必須與t的某個建構函式匹配,如下

//指向乙個值為42的int的share_ptr

share_ptr p3 = make_share (42);

//指向乙個值為"999999999"的string

share_ptr p4 = make_share (10, 9);

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

auto p6 = make_shared();

share_ptr的拷貝和賦值

當進行拷貝或者賦值操作時,每個share_ptr都會記錄有多少個其他share_ptr指向相同的物件:

auto p = make_share (42);//p指向的物件只有p乙個引用者

auto q§;//p和q指向相同物件,此物件有兩個引用者。

我們可以認為每個share_ptr都有乙個關聯的計數器,通常稱其為引用計數(reference count)。無論何時我們拷貝乙個share_ptr,計數器都會遞增。

例如:當用乙個share_ptr初始化另乙個share_ptr,或將它作為引數傳遞給乙個函式以及作為函式的返回值時,它所關聯的計數器就會遞增。當我們給share_ptr賦予乙個新值或是share_ptr被銷毀(例如乙個區域性的share_ptr離開其作用域時,計數器就會遞減)。

一旦乙個share_ptr的計數器變為0,它就會自動釋放管理的物件:

auto r = make_share (42)//r指向的int只有乙個引用值

r = q;//給r賦值,令它指向另乙個位址

//遞增q指向的物件的引用計數

//遞減r的引用計數

//r原來指向的物件已經沒有引用者,會自動釋放。

此例中我們分配了乙個int,將其指標儲存在r中。接下來,我們將乙個新值賦予r。在此情況下,r是唯一指向該int的share_ptr,在把q賦給r的過程中,此int自動釋放。

c 智慧型指標

auto prt 它是 它所指向物件的擁有者 所以當自身物件被摧毀時候,該物件也將遭受摧毀,要求乙個物件只有乙個擁有者,注意 auto prt 不能使用new 來分配物件給他 include include using namespace std template void bad print au...

c 智慧型指標

很久沒寫部落格了,不知道如何表達了,哈哈.我先介紹一下深淺拷貝.class copy 此時a.ptr和b.ptr指向同乙個物件,當我們delete a.ptr時 b.ptr所指向的物件已經不存在了,要是我們引用b.ptr指向的物件也就會出問題了.深拷貝 把a.ptr所指向的物件拷貝乙份給b.ptr ...

c 智慧型指標

記得前不久有一次面試被問到智慧型指標的實現,當時對智慧型指標只是聽說但沒有了解過,就亂七八糟地說了一遍。今天寫了一遍智慧型指標,用了引用計數的概念。主要思想就是,用乙個新類對原本需要的型別進行了一層封裝,這個新類中儲存了原本的物件指標和乙個引用計數的指標,之所以全部用指標來儲存,就是因為會出現多個新...