auto_ptr

  1. auto_ptr这个智能指针在c++11中已经被遗弃,原因如下:在拷贝与赋值操作时,智能指针所管理的对象会发生拥有权转移,如果这个时候程序员去使用已经被转移拥有权的智能指针,不会发生编译错误,却在访问管理的对象时导致程序运行出错。这是一种很危险的行为。因此在c++11中引入了unique_ptr,参见下篇。
  2. 示例如下:
#include <iostream>
#include <memory>
using namespace std;

int main() {
    auto_ptr<int> ptr1(new int(100));
    // 一个赋值操作导致ptr1失去了堆对象的拥有权(钥匙掉了开不了门)
    // auto_ptr<int> ptr2 = ptr1;

    // cout << *ptr1.get() << endl; // 指针的值为0,访问对象不可行

    // 同理,拷贝操作也是
    auto_ptr<int> ptr2(ptr1);
    cout << *ptr1.get() << endl; // 指针的值为0,访问对象不可行
    return 0;
}
  1. auto_ptr源码如下:
#include <cassert> // for assert

template<typename _Tp1>
struct auto_ptr_ref
{
    //内部指针
    _Tp1* _M_ptr;
    //有参构造函数
    explicit auto_ptr_ref(_Tp1* __p) : _M_ptr(__p) { }
};

template<typename _Tp>
class auto_ptr
{
private:
    _Tp* _M_ptr;

public:
    //指针的类型
    typedef _Tp element_type;

    explicit auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }

    // 拷贝构造发生所有权转移
    auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }

    //模板成员函数(泛型方法),_Tp1类型的指针必须能够转化为_Tp类型的指针
    template<typename _Tp1>
    auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }


    // 拷贝赋值运算符发生所有权转移
    auto_ptr& operator=(auto_ptr& __a) throw()
    {
        reset(__a.release());
        return *this;
    }

    //模板成员函数,_Tp1类型的指针必须能够转化为_Tp类型的指针
    template<typename _Tp1>
    auto_ptr& operator=(auto_ptr<_Tp1>& __a) throw()
    {
        reset(__a.release());
        return *this;
    }

    ~auto_ptr() { if (_M_ptr) delete _M_ptr; }

    //解除引用
    element_type& operator*() const throw()
    {
        //如果内部指针为空,则中止程序运行
        assert(_M_ptr != nullptr);
        return *_M_ptr;
    }

    //解除引用
    element_type* operator->() const throw()
    {
        assert(_M_ptr != nullptr);
        return _M_ptr;
    }

    //获取原始指针资源
    element_type* get() const throw() { return _M_ptr; }

    //核心:将auto_ptr管理的对象所有权转移
    element_type* release() throw()
    {
        element_type* __tmp = _M_ptr;
        _M_ptr = nullptr;
        return __tmp;
    }

    //核心:强制重置_M_ptr,析构资源,将_p赋值给_M_ptr
    void reset(element_type* __p = 0) throw()
    {
        if (__p != _M_ptr)
        {
            delete _M_ptr;
            _M_ptr = __p;
        }
    }

    //自动转化
    auto_ptr(auto_ptr_ref<element_type> __ref) throw()
        : _M_ptr(__ref._M_ptr) { }

    //将__ref的所有权转让给_M_ptr
    auto_ptr& operator=(auto_ptr_ref<element_type> __ref) throw()
    {
        if (__ref._M_ptr != this->get())
        {
            delete _M_ptr;
            _M_ptr = __ref._M_ptr;
        }
        return *this;
    }

    //类型转化函数
    template<typename _Tp1>
    operator auto_ptr_ref<_Tp1>() throw()
    {
        return auto_ptr_ref<_Tp1>(this->release());
    }

    //类型转换函数,将_Tp类型的指针对象_M_ptr转化为auto_ptr<_Tp1>
    template<typename _Tp1>
    operator auto_ptr<_Tp1>() throw()
    {
        return auto_ptr<_Tp1>(this->release());
    }
};

//模板特化版本
template<>
class auto_ptr<void>
{
public:
    typedef void element_type;
};