跳至內容

智慧指標

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書

智能指針(英語:Smart pointer)是一種抽象的資料類型。在程式設計中,它通常是經由類模板來實作,藉由模板來達成泛型,藉由類別的解構函數來達成自動釋放指標所指向的記憶體或物件。

C++中的智能指針

auto_ptr

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();
    };

}

unique_ptr

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中被標為"棄用".

shared_ptr和weak_ptr

基於Boost庫, C++11加入了shared_ptrweak_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(); // 因为内存已经被释放了,所以得到的是空指针。
ifp3
{
  // 不会执行到这。
}

外部連結