c++智慧指標(smart pointer)詳解
Smart Pointer
Deal with c++11’s smart pointer facility.
brief
Smart pointers are class objects that behave like built-in pointers but also manage objects that you create with new so that you don’t have to worry about when and whether to delete them - the smart pointers automatically delete the
managed object for you at the appropriate time.
- shared_ptr
- weak_ptr
- unique_ptr
shared_ptr (共享指標)
- referenced-counted smart pointer
- Shared Ownership with shared_ptr
引用計數智慧指標:可以和其他 boost::shared_ptr 型別的智慧指標共享所有權。 在這種情況下,當引用物件的最後一個智慧指標銷燬後或者被重新賦值或者使用了reset(),物件才會被釋放。多個shared_ptr物件可以擁有同一個物件。
在繼承中的例子:
shared_ptr<Thing> base_ptr(new Thing(2));
shared_ptr<Food> derived_ptr;
///if static_cast<Derived* >(base_ptr.get()) is valid, then the following is valid:
base_ptr->showID();
///cast failed
derived_ptr = static_pointer_cast<Food>(base_ptr);
shared_ptr<Food> a(new Food);
// a->showID();
derived_ptr->showID();
使用 make_shared 更加高效
There are actually two dynamic memory allocations that happen: one for the object itself from the new, and then a second for the manager object created by the shared_ptr constructor. Since memory allocations are slow, this means that creating a shared_ptr is slow relative to using either a raw pointer, or a so-called “intrusive” reference- counted smart pointer where the reference count is a member variable of the object. To address this problem, C++11 includes a function template make_shared that does a single memory allocation big enough to hold both the manager object and the new object, passing along any constructor parameters that you specify, and returns a shared_ptr of the specified type, which can then be used to initialize the shared_ptr that you are creating (with efficient move semantics).
shared_ptr<Thing> p(new Thing); // ouch - two allocations
shared_ptr<Thing> p1(make_shared<Thing>()); // only one allocation!
注意
- 使用 share_ptr copy assignment 或者建構函式會使shared_ptr的引用計數加1
- 使用 reset() 成員函式可以使當前share_ptr為空,刪除指向物件的指標
- 通過給share_ptr賦值 nullptr 可以達到第二條的效果
- 不允許原生指標與智慧指標之間的直接賦值轉換
- 不要直接從原生指標構造兩個功能相同的smart pointer,否則會造成double-deletion錯誤
- 可以通過 get() 函式獲得原生指標
- 在繼承關係或者其他的轉換時,可以使用
- static_pointer_cast
- dynamic_pointer_cast
- const_pointer_cast
weak_ptr
Weak pointers just “observe” the managed object; they don’t “keep it alive” or affect its lifetime. Unlike shared_ptrs, when the last weak_ptr goes out of scope or disappears, the pointed-to object can still exist because
the weak_ptrs do not affect the lifetime of the object - they have no ownership rights. But the weak_ptr can be used to determine whether the object exists, and to provide a shared_ptr that can be used to refer to it.
僅僅觀察被管理的物件,對其生命週期不產生任何影響
1.weak_ptr build-in-pointer might zero.
void do_it(weak_ptr<Thing> wp){
shared_ptr<Thing> sp = wp.lock();
// get shared_ptr from weak_ptr
if(sp)
sp->defrangulate(); // tell the Thing to do something
else
cout << "The Thing is gone!" << endl;
}
2.This approach is useful as a way to simply ask whether the pointed-to object still exists.
bool is_it_there(weak_ptr<Thing> wp) {
if(wp.expired()) {
cout << "The Thing is gone!" << endl;
return false;
}
return true;
}
3.if the weak_ptr is expired, an exception is thrown, of type
std::bad_weak_ptr.
void do_it(weak_ptr<Thing> wp){
shared_ptr<Thing> sp(wp); // construct shared_ptr from weak_ptr
// exception thrown if wp is expired, so if here, sp is good to go sp->defrangulate();
// tell the Thing to do something
}
try {
do_it(wpx);
}
catch(bad_weak_ptr&)
{
cout << "A Thing (or something else) has disappeared!" << endl;
}
4.inherit from enabled_shared_from_this\
否則會出現的錯誤 error:pointer being freed was not allocated
class Thing:public enable_shared_from_this<Thing>{
public:
int id;
public:
virtual void showID() const;
Thing();
Thing(int _id);
void foo();
};
void Thing::foo() {
shared_ptr<Thing> t1 = shared_from_this();
t1->showID();
}
公有繼承enable_shared_from_this\ ,則Thing類有了一個weak_ptr 作為成員變數。當第一個shared_ptr建立時,從第一個shared_ptr中初始化該weak_ptr\,當需要一個指向this的share_ptr時呼叫shared_from_this()成員函式,返回一個由weak_prt\構造而來的shared_ptr\,使得返回的shared_ptr與第一次的shared_ptr是相同的 manage object.
注意
- weak_ptr 與 share_ptr 結合使用,僅通過從share_ptr的複製和賦值,或者來源與其他weak_ptr。
- lock() 函式檢查weak_ptr指向的物件是否存在,如果不存在返回一個空的share_ptr,否則返回一個指向該物件的share_ptr.
- 不能使用給weak_ptr賦值nullptr的方式,只能通過reset()方法
- expired()函式返回weak_ptr是否為存在非空物件。
- 在建構函式中不可以使用shared_from_this
- 儘可能多的搭配使用share_ptr和weak_ptr,自動化記憶體管理。
unique_ptr
With a unique_ptr, you can point to an allocated object, and when the unique_ptr goes out of scope, the pointed-to object gets deleted, and
this happens regardless of how we leave the function, either by a return or an exception being thrown somewhere.
unique_ptr implements a unique ownership concept - an object can be owned by only one unique_ptr at a time - the opposite of shared ownership.
unique_ptr 隱式的刪除了copy建構函式,和copy assignment操作符,不允許一個物件同時被多個unique_ptr擁有這恰恰與shared_ptr相反。
The unique ownership is enforced by disallowing (with =delete) copy construction and copy assignment.So unlike built-in pointers or shared_ptr, you can’t copy or assign a unique_ptr to another unique_ptr.
move semantics: the move constructor and move assignment operator are defined for unique_ptr so that they transfer ownership from the original owner to the new owner.
可以通過move建構函式和move assignment 操作符使得unique_ptr的所屬權從原來的轉移到新的。轉移之後原來的unique_ptr不包含任何物件。
隱式的從右值轉換
unique_ptr<Thing> create_Thing()
{
unique_ptr<Thing> local_ptr(new Thing);
return local_ptr; // local_ptr will surrender ownership
}
void foo() {
unique_ptr<Thing> p1(create_Thing()); // move ctor from returned rvalue
// p1 now owns the Thing
unique_ptr<Thing> p2; // default ctor'd; owns nothing
p2 = create_Thing(); // move assignment from returned rvalue // p2 now owns the second Thing
}
顯式的使用move assignment 和 move construction進行轉換
unique_ptr<Thing> p1(new Thing); // p1 owns the Thing
unique_ptr<Thing> p2; // p2 owns nothing
// invoke move assignment explicitly
p2 = std::move(p1); // now p2 owns it, p1 owns nothing
// invoke move construction explicitly
unique_ptr<Thing> p3(std::move(p2)); // now p3 owns it, p2 and p1 own nothing
注意
- 通過reset()函式或者給unique_ptr賦值nullptr,可以手工的刪除物件。
reference
相關推薦
c++智慧指標(smart pointer)詳解
Smart Pointer Deal with c++11’s smart pointer facility. brief Smart pointers are class objects that behave like built-in
C++ 智慧指標(Smart Pointer)
智慧指標具有非常強大的能力,謹慎而明智的選擇能帶來極大的好處。我不否認智慧指標的能力,雖然我在之前的否認過auto_ptr。可能由於我自身能力的限制,體會不到auto_ptr的好處,但這樣的可能性我覺得已經不大了。但auto_ptr是最簡單的智慧指標,在它的周圍存在大量的作品
C++中的智慧指標(smart pointer)
指標問題是在學習C++,以及運用C++進行軟體開發過程中經常碰到的問題。其中之一,就是“懸垂指標”。所謂懸垂指標,就是是指指標指向了一塊沒有分配給使用者使用的記憶體,結果未定義,往往導致程式錯誤,而且難以檢測。 用一個簡單的例子來說明懸垂指標: string *sp = n
【C++】智慧指標(Smart Pointer)
1. 傳統指標存在的問題 傳統指標存在諸多的問題,比如指標所指向的物件的生命週期問題,掛起引用(dangling references),以及記憶體洩露(memory leaks). 如下是一個傳統指標的使用過程 void Foo() {
[C++] 什麼是智慧指標(Smart Pointer)以及何時使用
答案 1 智慧指標是一個類,它封裝了一個原始的C++指標,以管理所指物件的生命期。沒有單一的智慧指標型別,但所有這些都嘗試以實用的方式抽象原始指標。 智慧指標應優先於原始指標。 如果你覺得你需要使用指標(首先要考慮你是否真的需要指標),你通常會想要使用智慧指
C++深度探索系列:智慧指標(Smart Pointer) [二]
深度探索智慧指標(Smart Pointer) 主題索引: 一、剖析C++標準庫智慧指標(std::auto_ptr) 1.Do you Smart Pointer? 2
C++ 函式指標及其作用詳解
查了很多資料,對函式指標已瞭解。 函式指標指向某種特定型別,函式的型別由其引數及返回型別共同決定,與函式名無關。舉例如下: int add(int nLeft,int nRight);//函式定義 該函式型別為int(
智慧指標(smart pointer)(2):unique_ptr
Unique pointer: Manages the storage of a pointer, providing a limited garbage-collection facility, with little to no overhead ov
智慧指標boost::weak_ptr 詳解
1、boost::weak_ptr簡介 boost::weak_ptr屬於boost庫,定義在namespace boost中,包含標頭檔案 #include<boost/weak_ptr.hpp>便可以使用。 2、boost::weak_ptr
深度探索智慧指標(Smart Pointer)
主題索引: 一、剖析C++標準庫智慧指標(std::auto_ptr) 1.Do you Smart Pointer? 2.std::auto_ptr的設計原理 3.std::auto_ptr高階使用指南 4.你是否覺得std::auto_p
C++ 智慧指標詳解
C++ 智慧指標詳解 一、簡介 由於 C++ 語言沒有自動記憶體回收機制,程式設計師每次 new 出來的記憶體都要手動 delete。程式設計師忘記 delete,流程太複雜,最終導致沒有 de
c++智慧指標詳解
C++ 智慧指標詳解 一、簡介 由於 C++ 語言沒有自動記憶體回收機制,程式設計師每次 new 出來的記憶體都要手動 delete。程式設計師忘記 delete,流程太複雜,最終導致沒有 delete,異常導致程式過早退出,沒有執行 delete 的情況並不罕見。
C++ this指標的詳解 C++中this指標的用法詳解
C++中this指標的用法詳解 轉自:http://blog.chinaunix.net/uid-21411227-id-1826942.html 1. this指標的用處: 一個物件的this指標並不是物件本身的一部分,不會影響sizeof(物件)的結果
c++中this指標的用法詳解
為什麼引入this指標? 最簡單的應用場景就是:當我們在類中定義了一個變數,同時在類成員函式中定義了同一變數時,也就是說變數名重複時,但是我們想使用類中定義的變數,這個時候我們該怎麼辦呢?這個時候就是this指標大顯身手的時候了。為此我們引入this指標
C++ 中 this 指標的用法詳解
1. this指標的用處: 一個物件的this指標並不是物件本身的一部分,不會影響sizeof(物件)的結果。this作用域是在類內部,當在類的非靜態成員函式中訪問類的非靜態成員的時候,編譯器會自動將物件本身的地址作為一個隱含引數傳遞給函式。也就是說,即使你沒有寫上
C++拷貝構造函數詳解
public 類對象 -m 都是 出錯 ons const 需要 new 轉自:http://blog.csdn.net/lwbeyond/article/details/6202256/ 一. 什麽是拷貝構造函數 首先對於普通類型的對象來說,它們之間的復制是很簡單的,例如
C++11 std::chrono庫詳解
toolbar space max mil exp 值類型 cond 精度 ++i 所謂的詳解只不過是參考www.cplusplus.com的說明整理了一下,因為沒發現別人有詳細講解。 chrono是一個time library, 源於boost,現在已經是C++標準。
C++ 智能指針詳解(轉)
include 復雜 測試類 信息 思想 編譯 應該 其他 eas C++ 智能指針詳解 一、簡介 由於 C++ 語言沒有自動內存回收機制,程序員每次 new 出來的內存都要手動 delete。程序員忘記 delete,流程太復雜,最終導致沒有 delete,異常導致程
【轉】 C語言文件操作詳解
pri void rfi 識別 archive format 隨機 stat 文本文 轉自:http://www.cnblogs.com/likebeta/archive/2012/06/16/2551780.html C語言中沒有輸入輸出語句,所有的輸入輸出功能都用
關於windows下的c++的rand函數詳解
c++ rand rand不是真正的隨機函數,是偽隨機函數srand設置隨機函數種子srand設置一個參數後,每調用一次rand產生一個隨機數srand(1000001)rand – 21589rand – 29335rand – 14469 srand參數相同,多次調用rand依次返回的