文章目錄
-
- 寫在前面
- 一、unique_ptr
-
- 1. 不支援複制和指派,隻支援移動
- 2. 性能
- 二、shared_ptr
-
- 1. 支援複制,也支援移動
- 2. 性能
- 三、weak_ptr
- 四、選擇哪種指針作為函數的參數
寫在前面
本文主要總結一下 C++ 智能指針的正确使用方式,以下内容主要是對下面參考連結的總結、轉載,文中的詳細解釋請參考原連結,如有侵權,請聯系删除。
參考連結:
[1] C++ 智能指針的正确使用方式 https://www.cyhone.com/articles/right-way-to-use-cpp-smart-pointer/
一、unique_ptr
我們大多數場景下用到的應該都是
unique_ptr
。
1. 不支援複制和指派,隻支援移動
unique_ptr
代表的是專屬所有權,即由
unique_ptr
管理的記憶體,隻能被一個對象持有。
是以,
unique_ptr
不支援複制和指派。如果想要把
w
複制給
w2
, 是不可以的。因為複制從語義上來說,兩個對象将共享同一塊記憶體。
是以,
unique_ptr
隻支援移動。
2. 性能
因為 C++ 的 zero cost abstraction 的特點,unique_ptr 在預設情況下和裸指針的大小是一樣的。
是以 記憶體上沒有任何的額外消耗,性能是最優的。
二、shared_ptr
在使用
shared_ptr
之前應該考慮,是否真的需要使用
shared_ptr
, 而非
unique_ptr
。
1. 支援複制,也支援移動
shared_ptr
代表的是共享所有權,即多個
shared_ptr
可以共享同一塊記憶體。
是以,從語義上來看,
shared_ptr
是支援複制的。s
hared_ptr
也支援移動。從語義上來看,移動指的是所有權的傳遞。
隻要将
new
運算符傳回的指針
p
交給一個 shared_ptr 對象“托管”,就不必擔心在哪裡寫
delete p
語句——實際上根本不需要編寫這條語句,托管
p
的
shared_ptr
對象在消亡時會自動執行delete p。
多個
shared_ptr
對象可以共同托管一個指針
p
,當所有曾經托管
p
的
shared_ptr
對象都解除了對其的托管時,就會執行
delete p
。
2. 性能
- 記憶體占用高
- 原子操作性能低
-
使用移動優化性能
shared_ptr 在性能上固然是低于 unique_ptr。而通常情況,我們也可以盡量避免 shared_ptr 複制。
三、weak_ptr
weak_ptr 是為了解決 shared_ptr 雙向引用的問題。
weak_ptr 不會增加引用計數,是以可以打破 shared_ptr 的循環引用。
通常做法是 parent 類持有 child 的 shared_ptr, child 持有指向 parent 的 weak_ptr。這樣也更符合語義。
四、選擇哪種指針作為函數的參數
很多時候,函數的參數是個指針。這個時候就會面臨選擇困難症,這個參數應該怎麼傳,應該是 shared_ptr,還是 const shared_ptr&,還是直接 raw pointer 更合适。
-
隻在函數使用指針,但并不儲存對象内容
假如我們隻需要在函數中,用這個對象處理一些事情,但不打算涉及其生命周期的管理,也不打算通過函數傳參延長 shared_ptr 的生命周期。
對于這種情況,可以使用 raw pointer 或者 const shared_ptr&。
即:
void func(Widget*);
void func(const shared_ptr<Widget>&)
實際上第一種裸指針的方式可能更好,從語義上更加清楚,函數也不用關心智能指針的類型。
-
在函數中儲存智能指針
假如我們需要在函數中把這個智能指針儲存起來,這個時候建議直接傳值。
這樣的話,外部傳過來值的時候,可以選擇 move 或者指派。函數内部直接把這個對象通過 move 的方式儲存起來。
這樣性能更好,而且外部調用也有多種選擇。
參考連結:
[1] C++ 智能指針的正确使用方式 https://www.cyhone.com/articles/right-way-to-use-cpp-smart-pointer/