通常是經由類模板來實現。藉由模板來達成泛型,通常藉由類的析構函式來達成自動釋放指標所指向的記憶體或物件。
智慧型指標的最初動機是使得下面的**更安全,最初使用
void foo()
當上面的foo()函式出現異常時:
void foo()
catch (...)
}
當程式**越來越長時,程式**會顯得臃腫不堪
auto_ptr:
在使用auto_ptr時,須十分注意資源所有權的概念。auto_ptr是現在標準庫裡面乙個輕量級的智慧型指標的實現,存在於標頭檔案 memory中,之所以說它是輕量級,是因為它只有乙個成員變數(擁有物件的指標),相關的呼叫開銷也非常小。
當有了智慧型指標時我們可以將上面的**進行如下改寫:
void foo()
下面我們來看看auto_ptr實現了些什麼:(以下的auto_ptr的宣告摘自iso/iec 14882, section 20.4.5:)
namespace
std ;
template
class
auto_ptr ;
}
再來看看賦值運算子的過載和拷貝構造的寫法:
//拷貝構造
auto_ptr(_myt& _right) _throw0()
: _myptr(_right.release())
{}auto_ptr(auto_ptr_ref<_ty> _right) _throw0()
//賦值
_myt& operator=(_myt& _right) _throw0()
_myt& operator=(auto_ptr_ref<_ty> _right) _throw0()
//release
_ty *release() _throw0()
eg1:
myclass* p(new
myclass);
myclass* q = p;
delete p;
p->dosomething();
p = null;
q->dosomething();
可以看出:auto_ptr只是簡單的把新構造的物件q 指向了p 的記憶體空間。delete p 之後 p 可能依然指向某塊記憶體(懸掛的)但是卻是無效的指標。
eg2:
void main()
eg3:
void main()
q指向了p的記憶體,出作用域後先析構q,p指向空然而這時的p已經找不到了,導致p依然指向某塊記憶體,但卻是無效的指標。
簡潔版auto_ptr:
template
class smartptr
~ smartptr()
}smartptr(smartptr & ap)
: _ptr(ap ._ptr)
smartptr& operator =(smartptr& ap)
return *this ;
}t* getptr()
t& operator * ()
t* operator -> ()
private :
t* _ptr ;
};void test1 ()
auto_ptr的幾點注意事項:
1、auto_ptr不能共享所有權
2、auto_ptr不能指向陣列
3、auto_ptr不能作為容器的成員
4、不能通過複製操作來初始化auto_ptr
std::auto_ptr p(new int(42)); //ok
std::atuo_ptrp = new int(42);//error
這是因為auto_ptr的建構函式被定義了explicit
5、不要把auto_ptr放入容器
物件複製給另乙個 auto_ptr p2物件以後,p1則被置空,如果訪問p1,則會出現非法訪問, auto_ptr 的介面設計存在缺陷!
uniqu-ptr(socped_ptr):
uniqu_ptr的拷貝建構函式和賦值運算子都宣告為deleted,也就是說它不能被拷貝,只能通過std::move來轉遞它所指向的記憶體的所有權。
std:
:unique_ptr p1(new int(5));
std:
:unique_ptr p2 = p1; // 編譯會出錯
std:
:unique_ptr p3 = std:
:move (p1); // 轉移所有權,現在那塊記憶體歸p3所有, p1成為無效的指標。
p3.reset(); //釋放記憶體。
p1.reset(); //實際上什麼都沒做。
std:
:auto_ptr依然存在,但在c++11中被標為"棄用".
簡潔版unique_ptr:
template class smartptr
~ smartptr()
}t* getptr()
t& operator * ()
t* operator -> ()
private :
smartptr(smartptr & ap);
smartptr& operator =(smartptr& ap);
//!=
//== 拷貝構造 和賦值 不被允許 則這兩個也沒有意義
private :
t* _ptr ;
};void test1 ()
shared_ptr
shared_ptr物件除了包括乙個所擁有物件的指標(px)外,還必須包括乙個引用計數**物件(shared_count)的指標(pn)。而這個引用計數**物件包括乙個真正的多型的引用計數物件(sp_counted_base)的指標(_pi),真正的引用計數物件在使用vc編譯器的情況下包括乙個虛表,乙個虛表指標,和兩個計數器
shared_ptr完美解決auto_ptr在物件所有權上的侷限性(auto_ptr是獨佔的),在使用引用計數的機制上提供了可以共享所有權的智慧型指標。
template
class smartptr
~ smartptr()
smartptr(const smartptr& ap)
: _ptr(ap ._ptr)
, _countptr(ap ._countptr)
smartptr& operator =(const smartptr& ap )
return *this ;
}t* getptr ()
int getcount ()
t& operator * ()
t* operator -> ()
protected :
void release ()}}
private :
t* _ptr ;
int* _countptr ;
};void test1 ()
~ smartarrayptr()
smartarrayptr(const smartarrayptr& ap)
: _ptr(ap ._ptr)
, _countptr(ap ._countptr)
smartarrayptr& operator =(const smartarrayptr& ap)
return *this ;
}t* getptr ()
int getcount ()
t& operator (size_t index)
protected :
void release ()}}
private :
t* _ptr ;
int* _countptr ;
};void test2 ()
boost庫中智慧型指標的發展
boost庫下各種智慧型指標的發展 智慧型指標的發展是為了解決記憶體洩漏的情況而誕生,在大型工程中,即時足夠小心的保證new和delete 匹配出現。但無法避免throw的異常丟擲導致一段程式的提前結束而產生的記憶體洩漏。誕生智慧型指標,用類封裝原生指標。auto ptr 引入乙個所有權的概念。指向...
智慧型指標 強弱智慧型指標
在平時編寫 的時候經常會用到new來開闢空間,而我們開闢出來的空間必須得手動去delete他,但是如果程式設計師忘記去手動釋放那邊會出現乙個麻煩的問題,記憶體洩漏!或者是一塊記憶體被多個函式同時使用時,如果其中乙個函式不知道還有其他人也在使用這塊記憶體而釋放掉的話同樣也會引起程式的崩潰。引起記憶體洩...
智慧型指標(二)智慧型指標的方法和構造
預設構造shared ptrsp和unique ptrup 指標構造shared ptrsp t 和unique ptrup t 這裡預設為explicit 帶刪除器的構造shared ptrp q,d q這裡可以內建指標和智慧型指標,同時將用d析構器代替delete。所以定義了這麼乙個帶刪除器的建...