shared ptr的使用和陷阱

2022-03-26 14:32:36 字數 2402 閱讀 8638

//make_shared分配一塊int型別大小的記憶體,並值初始化為100

//返回值是shared_ptr型別,因此可以直接賦值給sp

shared_ptr sp = make_shared(100);

//錯誤! 不會進行隱式轉換,型別不符合

shared_ptr sp1 = new int(100);

//正確,直接初始化呼叫建構函式

shared_ptr sp2(new int(100000));

分配好了記憶體空間,我們就可以使用shared_ptr定義的操作了

多個共享指標指向同乙個空間,它們的關係可能是關聯(我們所期望的正常關係)或是獨立的(一種錯誤狀態)

shared_ptr sp1(new int(10));

shared_ptr sp2(sp1), sp3;

sp3 = sp1;

//乙個典型的錯誤用法

shared_ptr sp4(sp1.get());

cout << sp1.use_count() << " " << sp2.use_count() << " "

<< sp3.use_count() << " " << sp4.use_count() << endl;

//輸出 3 3 3 1

sp1,sp2,sp3是相互關聯的共享指標,共同控制所指記憶體的生存期,sp4雖然指向同樣的記憶體,卻是與sp1,sp2,sp3獨立的,sp4按自己的引用計數來關聯記憶體的釋放。

只有用乙個shared_ptr為另乙個shared_ptr賦值時,才將這連個共享指標關聯起來,直接使用位址值會導致各個shared_ptr獨立。

有時候我們需要用智慧型指標管理非new的物件,或者是沒有析構函式的類,由於shared_ptr預設使用delete來釋放記憶體並執行析構函式,對於以上的兩種情況是不適用的,所以我們要傳遞特別的刪除器

刪除器必須接受單個型別為 t* 的引數

//沒有析構函式的類

struct mystruct

//建構函式中申請了一塊記憶體

//用裸指標管理,不用時需要手動釋放

};void main()

); }

// 離開作用域,呼叫傳遞的刪除器釋放sp所指的記憶體空間

}

對於以上這個例子,首先不可以用delete來釋放區域性物件,然後mystruct也沒有析構函式來釋放申請的空間,所以向管理它的shared_ptr傳遞乙個刪除器來做這兩件事。

關於獨立的shared_ptr的意思及危害上面已經說出,遵守下面幾點來避免這個錯誤

不要與裸指標混用

//錯誤場景1

int *x(new int(10));

shared_ptr sp1(x);

shared_ptr sp2(x);

//雖然sp1、sp2都指向x所指的記憶體,但他們是獨立的,

//會在其他shared_ptr還在使用記憶體的情況下就釋放掉記憶體

//失去了設計共享指標的意義

//同時,使用裸指標x本身也是很危險的,x隨時可能變成空懸指標而無從知曉

//錯誤場景2

//函式接受乙個共享指標引數

void func(shared_ptr sp);

int *x(new int(10));

//建立了乙個指向x指標所指記憶體的共享指標,引用計數為1,是引用這塊記憶體的唯一共享指標

func(shared_ptr (x));

//離開函式即離開共享指標的作用域,這塊記憶體即被刪除

不要用p.get()的返回值為shared_ptr賦值

shared_ptr sp1(new int(10));

//sp2與sp1獨立

shared_ptr sp2(sp1.get()),sp3;

//sp3與sp1獨立

sp.reset(sp1.get());

p.get()的返回值就相當於乙個裸指標的值,不合適的使用這個值,上述陷阱的所有錯誤都有可能發生,遵守以下幾個約定

不要儲存p.get()的返回值 

無論是儲存為裸指標還是shared_ptr都是錯誤的 

儲存為裸指標不知什麼時候就會變成空懸指標 

儲存為shared_ptr則產生了獨立指標

不要delete p.get()的返回值 

會導致對一塊記憶體delete兩次的錯誤

如果用shared_ptr管理非new物件或是沒有析構函式的類時,應當為其傳遞合適的刪除器

unique ptr的使用和陷阱

與shared ptr不同,unique ptr沒有定義類似make shared的操作,因此只可以使用new來分配記憶體,並且由於unique ptr不可拷貝和賦值,初始化unique ptr必須使用直接初始化的方式。unique ptr up1 new int okay,直接初始化 unique...

unique ptr的使用和陷阱

與shared ptr不同,unique ptr沒有定義類似make shared的操作,因此只可以使用new來分配記憶體,並且由於unique ptr不可拷貝和賦值,初始化unique ptr必須使用直接初始化的方式。unique ptrup1 new int okay,直接初始化 unique ...

C 11智慧型指標Shared ptr陷阱

1.不要把乙個原生指標給多個shared ptr管理 int ptr new int shared ptr p1 ptr shared ptr p2 ptr logic error ptr物件被刪除了2次2.不要把this指標給shared ptr class test private shared...