C Primer 筆記 智慧型指標

2022-08-19 05:09:12 字數 4139 閱讀 6022

1.新的標準庫提供了兩種智慧型指標型別,shared_ptr允許多個指標指向同乙個物件,unique_ptr則獨佔所指的物件。標準庫還定義了乙個名為weak_ptr的伴隨類,它是一種弱引用,指向shared_ptr所管理的物件。

2.智慧型指標也是模板,預設初始化的智慧型指標中儲存著乙個空指標。

3.智慧型指標的操作:

4.make_shared用引數來構造指定型別的物件。

std::shared_ptr p = std::make_shared(42);    //指向乙個值為42的int型shared_ptr

std::shared_ptrstring> p1 = std::make_sharedstring>(2,'1'); //指向乙個值為"11"的string型別shared_ptr

std::shared_ptr p2 = std::make_shared(); //值初始化為0

5.我們可以認為每個shared_ptr有乙個引用計數,無論何時我們拷貝乙個shared_ptr,計數器都會遞增,當我們給shared_ptr賦予乙個新值或是shared_ptr被銷毀時,計數器就會遞減。

6.當指向乙個物件的最後乙個shared_ptr被銷毀時,shared_ptr類會自動銷毀此物件。它是通過析構函式完成銷毀工作的。所占用的記憶體也會被釋放。

7.shared_ptr在無用之後仍然保留的一種可能情況是,你將shared_ptr放在乙個容器中(其實已經做了拷貝),隨後重排了容器,從而不再需要某些元素,而只使用其中一部分,所以要記得用erase刪除不再需要的那些元素。

8.在自由空間分配的記憶體是無名的,因此new無法為其分配的物件命名,而是返回乙個指向該物件的指標。

9.預設情況下,動態分配的物件是預設初始化的。這意味著內建型別或組合型別的值將是為定義的,而類型別的物件將用預設建構函式進行初始化。也可以對動態分配的記憶體進行值初始化,只需在型別名之後跟一對空括號即可。

int *p = new int;    //預設初始化,*p的值未定義

int *p1 = new int(); //值初始化為0,*p1為0

10.當我們提供乙個括號包圍的初始化器,就可以使用auto從此初始化器來推斷我們想要分配的物件的型別,但是正因如此,只有當括號中僅有單一初始化器時才可以使用auto。

int

a, b;

int i = 1

;auto p = new auto(i); //

p指向乙個值為1的int型,但不是指向i

auto p1 = new auto; //

錯誤,括號中只能有單個初始化器

11.定位new表示式允許我們向new傳遞額外的引數。

int *p = new

int; //

如果分配失敗,new丟擲std::bad_alloc

int *p1 = new (std::nothrow) int; //

如果分配失敗,new返回乙個空指標

12.我們傳遞給idelete的指標必須指向動態分配的記憶體,或者是乙個空指標。釋放一塊並非new分配的記憶體,或者將相同的指標值釋放多次,其行為是未定義的。

13.我們可以用new返回的指標來初始化智慧型指標,接受指標引數的智慧型指標建構函式是explicit的,因此不能將乙個內建指標隱式轉換為乙個只能指標,必須使用直接初始化形式來初始化乙個智慧型指標。

std::shared_ptr p = new

int(1); //

錯誤,必須使用直接初始化形式

std::shared_ptr p1(new

int(1)); //

正確,使用了直接初始化形式

14.預設情況下,乙個用來初始化智慧型指標的普通指標必須指向動態記憶體,因為智慧型指標預設使用delete釋放它所關聯的物件,我們可以將智慧型指標繫結到乙個指向其他型別的資源的指標上,但是為了這樣做,必須提供自己的操作來代替delete。

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

16.使用乙個內建指標來訪問乙個智慧型指標所負責的物件是很危險的,因為我們無法知道物件何時會被銷毀。

void test(std::shared_ptrp)

int *p = new

int(42); //

p是乙個普通指標,不是乙個智慧型指標

test(p); //

錯誤,不能將int*轉換為乙個shared_ptr

test(std::shared_ptr(p)); //

合法的,但是一旦函式呼叫結束,p指向的記憶體就被釋放了

int j = *p; //

未定義的,p是乙個空懸指標

17.get用來將指標的訪問許可權傳遞給**,你只有在確定**不會delete指標的情況下,才能使用get。特別的,永遠不要用get初始化另乙個智慧型指標或者為另乙個智慧型指標賦值。

std::shared_ptr p(new

int(1)); //

p的引用計數為1

int *q = p.get(); //

正確,但是注意不要讓q被釋放

if (1

)

//程式塊結束,p1被銷毀,所指的記憶體被釋放

int i = *p; //

未定義,p所指的記憶體被釋放了

18.與賦值類似,reset會更新引用計數,如果需要的話,會釋放p指向的物件。reset經常與unique一起使用。

std::shared_ptr p(new

int(1

));

//...

if (!p.unique())

p.reset(

newint(2)); //

我們不是唯一使用者,分配新的拷貝

else

(*p)++; //

我們是唯一使用者,可以直接改變物件的值

19.如果在new和delete之間發生異常,且異常未**獲,則記憶體就永遠不會被釋放,使用智慧型指標就可以避免這個問題。

20.當乙個shared_pt(unique_ptr也一樣)r被銷毀時,缺省會對它管理的指標進行delete操作,我們可以自己定義乙個刪除器函式來代替delete操作。

class

test;};

void my_delete(test *t)

std::shared_ptr

p(new test(), my_delete); //

p被銷毀時會呼叫my_delete

21.unique_ptr也必須採用直接初始化的形式,而且unique_ptr不支援普通的拷貝或賦值操作,但是有如下操作。

22.不能拷貝unique_ptr的規則有乙個例外,我們可以拷貝或賦值乙個將要被銷毀的unique_ptr。

std::unique_ptr clone(int

i)//

orstd::unique_ptr clone1(int

i)

23.weak_ptr是一種不控制所指向物件生存期的智慧型指標,它指向乙個shared_ptr管理的物件。所以weak_ptr不會改變shared_ptr的引用計數。

24.weak_ptr定義了如下操作:

25.由於物件可能不存在,我們不能使用weak_ptr直接訪問物件,而必須呼叫lock.

std::shared_ptr p(new

int(1

));std::weak_ptr

p1(p);

if (std::shared_ptr np = p1.lock()) //

如果np為空則不可操作

c primer筆記 智慧型指標

智慧型指標的陷阱 基本規範 1.不使用相同的內建指標值初始化 或reset 多個智慧型指標。double free 2.不delete get 返回的指標。double free 3.不使用get 初始化或reset另乙個智慧型指標。double free 4.如果你使用get 返回的指標,記住當最...

讀C Primer 之智慧型指標

author xizero00 mail xizero00 163.com date 2011 08 07 20 19 11 smart pointer sample include using namespace std 智慧型指標類 class smartptr 析構函式 smartptr 使用...

動態記憶體與智慧型指標(C Primer 筆記)

auto p make shared int 42 p指向的物件只有p乙個引用者 auto q p p和q指向相同物件,此物件有兩個引用者shared ptr int p1 newint 1024 錯誤,必須使用直接初始化形式 shared ptr int p2 newint 1024 正確,p1的...