1. 程式人生 > >c++智慧指標

c++智慧指標

靜態記憶體和棧記憶體。靜態記憶體用來儲存區域性的static物件、類的static資料成員以及定義在任何函式之外的變數。棧記憶體用來儲存定義在函式內的非static的物件。分配在靜態或者棧記憶體中的物件由編譯器自動建立和銷燬。 對於棧物件,僅在其定義的程式執行時才存在;static物件在使用之前分配,在程式結束時銷燬。 除了靜態記憶體和棧記憶體之外,每個程式還擁有一個記憶體池。這部分記憶體被稱作自由空間或堆。程式用堆來儲存動態分配的物件-即那些在程式執行時分配的物件。動態物件的生存週期由程式來控制,也就是程式不在使用時,我們程式碼必須顯式的銷燬它。 但是動態物件的正確釋放被證明是程式設計中極其容易出錯的地方。為了更安全地使用動態物件,標準庫定義了兩個智慧指標型別來動態管理動態分配的物件。當一個物件應該被釋放時,指向它的智慧指標可以確保自動的釋放它。 動態記憶體的管理是通過一對運算子號來完成的:new,在動態記憶體中為物件分配記憶體空間並返回一個指向該物件的指標,我們可以選擇對物件進行初始化;delete,接受一個動態物件的指標,銷燬該物件,並釋放與之關聯的記憶體。

為了更容易的使用動態記憶體,新的標準提出兩種智慧指標:重要的區別是它負責自動釋放所指向的物件。 shared_ptr:允許多個指標指向同一個物件; unique_ptr則獨佔所指向的物件。 標準庫還定義了一個名為weak_ptr的伴隨類,它是一個弱引用,指向shared_ptr所管理的物件。這三個型別都定義在memory標頭檔案中。

share_ptr p1; //shared_ptr,可以指向string shared_ptr<list> p2; // shared_ptr,可以指向int的list

預設初始化的智慧指標中儲存著一個空指標。 智慧指標的使用方式與普通指標類似。解引用一個智慧指標返回指向的物件。如果一個條件判斷中使用智慧指標,效果就是檢測它是否為空。

if(p1&&p1->empty())  //如果p1不為空,檢測它是否指向一個空的string
*p1 = "hi";                    //如果p1指向一個空的string,解引用p1,將一個新值賦予string
share_ptr和unique_ptr都支援的操作

share_ptr<T> sp 空智慧指標,可以指向型別為T的物件
unique_ptr<T> up
p                      將用作一個判斷條件,若p指向一個物件,則為true
*p                     解引用p,獲得它指向的物件
p->mem                 等價於(*p).mem
p.get()                返回p中儲存的指標。要小心使用,若智慧指標釋放其物件,返回的指標指向的物件也就消失。
swap(p, q)             交換p和q中的指標
p.swap(q)
make_share<T> (args) 返回一個share_ptr,指向一個動態分配的型別為T的物件。使用args初始化此物件
share_ptr<T>p (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<vector>(); 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自動釋放。