C++11智慧指標用法
shared_ptr和unique_ptr都支援的操作:
*p
p->mem
p.get() 返回p中儲存的指標,智慧指標p在某些情況下可以代替p.get(),比如cout<<p 輸出內部指標
p.reset() 放棄內部物件的所有權,等價於 p = nullptr
p.reset(T *ptr) 變更擁有的物件
在shared中,reset會造成引用計數的減少,為0時刪除;unique中直接刪除
swap(p, q) 交換p和q中的指標
shared_ptr
建立
shared_ptr<T> p1; //預設初始化,儲存空指標
shared_ptr<T> p1(T* ptr); //建構函式,示例如下
shared_ptr<T> p1(new T());
shared_ptr<T> p2 = make_shared<T>(args);
shared_ptr<T> p3(p2); //拷貝構造,會增加p2中的計數器
//管理陣列,自動呼叫delete[]而不是delete
shared_ptr<T[]> up(new T[10]);
//不使用原本的delete釋放操作,自定義刪除器:
shared_ptr<T> p3(..., deleterFun); //定製void(T*)型別刪除器函式,或者函式物件或者lambda表示式
不能將普通指標直接賦值給智慧指標。
操作
p = q p和q都是shared_ptr,所儲存的指標必須能相互轉換。遞減p的引用計數,若為0則釋放;遞增q的引用計數。
p.unique() 返回是否是獨佔所有權
p.use_count() 返回引用計數
注意事項
不要使用同一個原始指標構造 shared_ptr:
int *num = new int(23);
std::shared_ptr<int> p1(num);
std::shared_ptr<int> p2(p1); // 正確使用方法
std::shared_ptr<int> p3(num); // 不推薦
std::cout << "p1 Reference = " << p1.use_count() << std::endl; // 輸出 2
std::cout << "p2 Reference = " << p2.use_count() << std::endl; // 輸出 2
std::cout << "p3 Reference = " << p3.use_count() << std::endl; // 輸出 1
雖然p1 p3指向相同物件,但並沒有統一,當p1超出作用域時會呼叫delete釋放num記憶體,此時num成了懸空指標,當p3超出作用域再次delete的時候就可能會出錯。
weak_ptr
weak_ptr 是為了配合shared_ptr而引入的一種智慧指標,對被 shared_ptr 管理的物件存在非擁有性(“弱”)引用,無法直接訪問,也不會影響引用計數。在訪問所引用的物件前必須先轉換為 shared_ptr。
weak_ptr<T> w 預設構造,空指標
weak_ptr<T> w(p) p為shared或weak,與p指向相同物件。T必須能轉換成p指向的型別
w = p 同上
w.reset() 將w置為空
w.use_count() w監視物件的引用計數
w.expired() w指向的物件引用計數是否為0,是為true
w.lock() 如果expired為true,返回空shared_ptr;否則返回一個指向w的shared_ptr
weak_ptr 用來表達臨時所有權的概念:當某個物件只有存在時才需要被訪問,而且隨時可能被他人刪除時,可以使用 weak_ptr 來跟蹤該物件。需要獲得臨時所有權時,則將其轉換為 shared_ptr(計數+1)。
if(shared_ptr<int> np = wp.lock()){ //如果np不為空則條件成立,計數暫時+1
// 在if中,np與p共享物件
}
//退出if函式體,計數-1恢復
weak_ptr 的另一用法是打斷 shared_ptr 所管理的物件組成的環狀引用。若這種環被孤立(例如無指向環中的外部共享指標),則 shared_ptr 引用計數無法抵達零,而記憶體被洩露。能令環中的指標之一為弱指標以避免此情況。
unique_ptr
unique_ptr<T> u1 //預設構造,儲存空指標
unique_ptr<T> up(T *ptr)
unique_ptr<T> up(new T)
//自定義刪除器,和shared_ptr不同,分別代表兩種不同的刪除器繫結方式:《C++primer 5th》P599
//1.shared_ptr在執行時繫結刪除器,刪除器儲存為一個指標,可以隨時通過reset來更改刪除器型別,更靈活;
//2.unique_ptr在編譯時繫結,因為刪除器的型別是unique_ptr型別的一部分,更高效。
unique_ptr<T, D> u2(new T) //用一個型別為D的可呼叫物件來代替delete
unique_ptr<T, D> u2(new T, d) //用型別為D的物件d代替delete
unique_ptr<T, decltype(deleterFun)*> u(dnew T, eleterFun) //使用刪除器函式,lambda同理
unique_ptr<T> up = make_unique<T>(args) //C++14起用
u.release() //返回指標,放棄控制權(並不釋放記憶體),將u置空,不同於reset
自定義刪除器:https://blog.csdn.net/DumpDoctorWang/article/details/88598015
unique_ptr獨佔指向的物件,不能拷貝或賦值unique_ptr,但可以通過呼叫release或reset轉移指標所有權:
unique_ptr<A> p(new A);
unique_ptr<A> p2(p.release());
unique_ptr<A> p3;
p3.reset(p2.release());
傳遞unique_ptr引數和返回unique_ptr
不能拷貝unique_ptr的規則有一個例外:我們可以拷貝或賦值一個將要被銷燬的unique_ptr。
unique_ptr<int> clone(int p){
unique_ptr<int> ret(new int(p));
//...
return ret;
}
編譯器知道要返回的物件將要被銷燬。在此情況下,編譯器執行移動賦值。
參考:
https://zh.cppreference.com/w/cpp/memory/unique_ptr
https://blog.csdn.net/DumpDoctorWang/article/details/88598015
https://blog.csdn.net/shaosunrise/article/details/85228823?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
《C++primer 5th》
相關文章
- 智慧指標用法學習指標
- c++11新特性實戰(二):智慧指標C++指標
- c++ 智慧指標用法詳解C++指標
- 指標的用法指標
- 智慧指標指標
- C語言指標用法大全C語言指標
- [CPP] 智慧指標指標
- 什麼是智慧指標?為什麼要用智慧指標?指標
- openfoam 智慧指標探索指標
- C++智慧指標C++指標
- 智慧指標之手撕共享指標shared_ptr指標
- C++ 指標常見用法小結C++指標
- c++動態記憶體智慧指標及weak_ptr用法的理解C++記憶體指標
- UE4 智慧指標指標
- C++ 用智慧指標這樣包裝 this 指標是否可行C++指標
- 指標+AI:邁向智慧化,讓指標應用更高效指標AI
- C++進階(智慧指標)C++指標
- 智慧指標和普通指標的區別指標
- C++11 noexcept 關鍵字用法學習C++
- C++標準庫有四種智慧指標C++指標
- C++筆記(11) 智慧指標C++筆記指標
- 【char* 字元指標的用法】及【輸出NULL的問題】字元指標Null
- 智慧指標-使用、避坑和實現指標
- C++11 標準庫 bind 函式C++函式
- 【C++】智慧指標的正確使用方式C++指標
- C++基於模板實現智慧指標C++指標
- 智慧指標引用計數變化學習指標
- C語言指標(三):陣列指標和字串指標C語言指標陣列字串
- 詳解c++指標的指標和指標的引用C++指標
- 陣列指標,指標陣列陣列指標
- c++11標準庫(第二版)C++
- 指標指標
- 聊聊 C++ 中的幾種智慧指標 (上)C++指標
- 【C++】 61_智慧指標類别範本C++指標
- 指標函式 和 函式指標指標函式
- 指標陣列與陣列指標指標陣列
- 第 10 節:複合型別-5. 指標 -- 指標與指標變數 -8. 多級指標型別指標變數
- C指標原理(15)-C指標基礎指標