C++智能指针 auto_ptr

auto_ptr 是一个轻量级的智能指针, 定义于 memory (非memory.h)中, 命名空间为 std. 
auto_ptr 适合用来管理生命周期比较短或者不会被远距离传递的动态对象, 最好是局限于某个函数内部或者是某个类的内部.

使用方法:
  std::auto_ptr<int> pt(new int(10));
  pt.reset(new int(11));

 

成员函数

  3个重要的函数:
  (1) get 获得内部对象的指针, 由于已经重载了()方法, 因此和直接使用对象是一样的.如 auto_ptr <int> sp(new int(1)); sp 与 sp.get()是等价的
  (2) release 放弃内部对象的所有权,将内部指针置为空, 返回所内部对象的指针, 此指针需要手动释放
    std::auto_ptr<int> ap0(new int(1));
    int* pa = ap0.release();
    delete pa; // 需要手动释放
  (3) reset 销毁内部对象并接受新的对象的所有权(如果使用缺省参数的话,也就是没有任何对象的所有权)

  其构造函数被声明为 explicit, 因此不能使用赋值符对其赋值(即不能使用类似这样的形式 auto_ptr<int> p = new int;)

 

auto_ptr 的特征

(1) auto_ptr 的对象所有权是独占性的. 
  auto_ptr 的拷贝构造和赋值操作符所接受的参数类型都是非const的引用类型(而一般都应该使用的const引用类型), 其原因在于为了使其内部能调用了 release 方法将原有的对象进行释放, 然后使用新对象替换原有的对象.
  因此导致动态对象的所有权被转移了, 新的 auto_ptr 独占了动态对象的所有权. 被拷贝对象在拷贝过程中被修改, 拷贝物与被拷贝物之间是非等价的.
  下面的使用方法将会出错:
    std::auto_ptr<int> pt1(new int(10));
    std::auto_ptr<int> pt2 = pt1;
    printf("pt1:%d\n", pt1); // 此时应输出 0 
    printf("pt1 value:%d\n", *pt1); // 错误, 对象已释放
(2) 不能将 auto_ptr 放入到标准容器中. 标准库容器无准备的拷贝行为, 会导致原 auto_ptr 内的对象被释放, 造成难以发觉的错误。

 

使用 auto_ptr 的注意事项

(1) auto_ptr 不能指向数组
(2) auto_ptr 不能共享所有权
(3) auto_ptr 不能通过复制操作来初始化
(4) auto_ptr 不能放入容器中使用
(5) auto_ptr 不能作为容器的成员
(6) 不能把一个原生指针给两个智能指针对象管理(对所有的智能指针).
  int* p = new int;
  auto_ptr<int> ap1(p);
  auto_ptr<int> ap2(p); // 错误, p不能给第二个智能指针对象. 会引起两次释放p

 

VC中的源码实现

template<class _Ty>

class auto_ptr

{    // wrap an object pointer to ensure destruction

public:

    typedef auto_ptr<_Ty> _Myt;

    typedef _Ty element_type;



    explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()

        : _Myptr(_Ptr)

    {    // construct from object pointer

    }



    auto_ptr(_Myt& _Right) _THROW0()

        : _Myptr(_Right.release())

    {    // construct by assuming pointer from _Right auto_ptr

    }



    auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()

    {    // construct by assuming pointer from _Right auto_ptr_ref

        _Ty *_Ptr = _Right._Ref;

        _Right._Ref = 0;    // release old

        _Myptr = _Ptr;    // reset this

    }



    template<class _Other>

    operator auto_ptr<_Other>() _THROW0()

    {    // convert to compatible auto_ptr

        return (auto_ptr<_Other>(*this));

    }



    template<class _Other>

    operator auto_ptr_ref<_Other>() _THROW0()

    {    // convert to compatible auto_ptr_ref

        _Other *_Cvtptr = _Myptr;    // test implicit conversion

        auto_ptr_ref<_Other> _Ans(_Cvtptr);

        _Myptr = 0;    // pass ownership to auto_ptr_ref

        return (_Ans);

    }



    template<class _Other>

    _Myt& operator=(auto_ptr<_Other>& _Right) _THROW0()

    {    // assign compatible _Right (assume pointer)

        reset(_Right.release());

        return (*this);

    }



    template<class _Other>

    auto_ptr(auto_ptr<_Other>& _Right) _THROW0()

        : _Myptr(_Right.release())

    {    // construct by assuming pointer from _Right

    }



    _Myt& operator=(_Myt& _Right) _THROW0()

    {    // assign compatible _Right (assume pointer)

        reset(_Right.release());

        return (*this);

    }



    _Myt& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()

    {    // assign compatible _Right._Ref (assume pointer)

        _Ty *_Ptr = _Right._Ref;

        _Right._Ref = 0;    // release old

        reset(_Ptr);    // set new

        return (*this);

    }



    ~auto_ptr()

    {    // destroy the object

        delete _Myptr;

    }



    _Ty& operator*() const _THROW0()

    {    // return designated value

#if _ITERATOR_DEBUG_LEVEL == 2

        if (_Myptr == 0)

            _DEBUG_ERROR("auto_ptr not dereferencable");

#endif /* _ITERATOR_DEBUG_LEVEL == 2 */



        return (*get());

    }



    _Ty *operator->() const _THROW0()

    {    // return pointer to class object

#if _ITERATOR_DEBUG_LEVEL == 2

        if (_Myptr == 0)

            _DEBUG_ERROR("auto_ptr not dereferencable");

#endif /* _ITERATOR_DEBUG_LEVEL == 2 */



        return (get());

    }



    _Ty *get() const _THROW0()

    {    // return wrapped pointer

        return (_Myptr);

    }



    _Ty *release() _THROW0()

    {    // return wrapped pointer and give up ownership

        _Ty *_Tmp = _Myptr;

        _Myptr = 0;

        return (_Tmp);

    }



    void reset(_Ty *_Ptr = 0)

    {    // destroy designated object and store new pointer

        if (_Ptr != _Myptr)

            delete _Myptr;

        _Myptr = _Ptr;

    }



private:

    _Ty *_Myptr;    // the wrapped object pointer

};

https://mp.weixin.qq.com/s?__biz=MzI3OTM4OTMzNA==&tempkey=MTAwNF9yWG9IM3YzTE93RDJZVUlYZTFLNlNFZlJHN0VyS1EzTklCdjIzNXNUUjdRdGc0VTVrckZ6RmQzSE0zTUhMTEhuVWEtcFhkQi05a3VFeTk4UXVaWTlvZEp3YnlFMi1tT0sxZDcwNm91UzRqNFI5MGJvbEVLcUxlZ2FPOGVDZU9GOWFuY0Vkb2F5eG9vZFdCWW5mc0hqTG15alZ6R1g4cHpEaDNEUTFRfn4%3D&chksm=6b4934af5c3ebdb9363ebaedc52bf8c66395544249fddd86cd19486a8c9b2048a047b3c16fa2#rd

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值