本页使用了标题或全文手工转换

智能指针

维基百科,自由的百科全书
跳转至: 导航搜索

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

C++中的智能指针[编辑]

auto_ptr[编辑]

auto_ptr這個類別模板被定義在en: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.

uniqu_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(); // 因为内存已经被释放了, 所以得到的是空指针.
if(p3)
{
  // 不会执行到这.
}

外部連結[编辑]