智慧型指標(英語:Smart pointer)是一種抽象的資料類型。在程式設計中,它通常是經由類別模板來實作,藉由模板來達成泛型,藉由類別的解構函式來達成自動釋放指標所指向的記憶體或物件。
C++中的智慧型指標
auto_ptr
這個類別模板被定義在ISO/IEC 14882的第20.4.5章節裡:
namespace std {
template <class Y> struct auto_ptr_ref {};
template <class X>
class auto_ptr {
public:
typedef X element_type;
// 20.4.5.1 construct/copy/destroy:
explicit auto_ptr(X* p =0)throw();
auto_ptr(auto_ptr&)throw();
template <class Y> auto_ptr(auto_ptr<Y>&)throw();
auto_ptr& operator=(auto_ptr&)throw();
template <class Y> auto_ptr& operator=(auto_ptr<Y>&)throw();
auto_ptr& operator=(auto_ptr_ref<X>)throw();
~auto_ptr() throw();
// 20.4.5.2 members:
X& operator*() const throw();
X* operator->() const throw();
X* get() const throw();
X* release() throw();
void reset(X* p =0)throw();
// 20.4.5.3 conversions:
auto_ptr(auto_ptr_ref<X>)throw();
template <class Y> operator auto_ptr_ref<Y>() throw();
template <class Y> operator auto_ptr<Y>() throw();
};
}
C++11中提供了std::unique_ptr
,定義在<memory>
標頭檔中。
C++11新增了move語意,相比copy語意,它能更好的實現值傳遞.std::auto_ptr
使用的是copy語意,為了向下相容,C++11沒有修改std::auto_ptr,而是引入了新的使用move語意的std::unique_ptr
.
unique_ptr的拷貝建構函式和設定運算子都聲明為deleted,也就是說它不能被拷貝,只能通過std::move
來轉遞它所指向的主記憶體的所有權。
std::unique_ptr<int> p1(new int(5));
std::unique_ptr<int> p2 = p1; // 编译会出错
std::unique_ptr<int> p3 = std::move (p1); // 转移所有权,现在那块内存归p3所有, p1成为无效的指针。
p3.reset(); //释放内存。
p1.reset(); //实际上什么都没做。
std::auto_ptr
依然存在,但在C++11中被標為"棄用".
基於Boost庫, C++11加入了shared_ptr
和weak_ptr
.它們最早在TR1中就被引入,但在C++11中,在Boost的基礎上又加入了新的功能。
std::shared_ptr
使用參照計數。每一個shared_ptr
的拷貝都指向相同的主記憶體。在最後一個shared_ptr
解構的時候,主記憶體才會被釋放。
std::shared_ptr<int> p1(new int(5));
std::shared_ptr<int> p2 = p1; // 都指向同一内存。
p1.reset(); // 因为p2还在,所以内存没有释放。
p2.reset(); // 释放内存,因为没有shared_ptr指向那块内存了。
std::shared_ptr
使用參照計數,所以有迴圈計數的問題。為了打破迴圈,可以使用std::weak_ptr
.顧名思義, weak_ptr是一個弱參照,只參照,不計數。如果一塊主記憶體被shared_ptr和weak_ptr同時參照,當所有shared_ptr解構了之後,不管還有沒有weak_ptr參照該主記憶體,主記憶體也會被釋放。所以weak_ptr
不保證它指向的主記憶體一定是有效的,在使用之前需要檢查。
std::shared_ptr<int> p1(new int(5));
std::weak_ptr<int> wp1 = p1; // 还是只有p1有所有权。
{
std::shared_ptr<int> p2 = wp1.lock(); // p1和p2都有所有权
if (p2) // 使用前需要检查
{
// 使用p2
}
} // p2析构了,现在只有p1有所有权。
p1.reset(); // 内存被释放。
std::shared_ptr<int> p3 = wp1.lock(); // 因为内存已经被释放了,所以得到的是空指针。
if(p3)
{
// 不会执行到这。
}
外部連結
- Sample chapter "Smart Pointers (頁面存檔備份,存於網際網路檔案館)" from the book Modern C++ Design: Generic Programming and Design Patterns Applied (頁面存檔備份,存於網際網路檔案館) by Andrei Alexandrescu, Addison-Wesley, 2001.
- Code example "countptr.hpp (頁面存檔備份,存於網際網路檔案館)" from the book The C++ Standard Library - A Tutorial and Reference (頁面存檔備份,存於網際網路檔案館) by Nicolai M. Josuttis
- "Boost Smart Pointers (頁面存檔備份,存於網際網路檔案館)"
- Article "The New C++: Smart (er) Pointers (頁面存檔備份,存於網際網路檔案館)" by Herb Sutter August 01, 2002
- "Smart Pointers - What, Why, Which? (頁面存檔備份,存於網際網路檔案館)" by Yonat Sharon
- "Smart Pointers Overview (頁面存檔備份,存於網際網路檔案館)" by John M. Dlugosz
- The YASPER library (頁面存檔備份,存於網際網路檔案館) Yet Another Smart Pointer implementation in C++
- Smart Pointers in Delphi (頁面存檔備份,存於網際網路檔案館)
Wikiwand in your browser!
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.