学习auto_ptr

来源:互联网 发布:面试礼仪 知乎 编辑:程序博客网 时间:2024/05/06 21:16

auto_ptr是std中的一个型别,是“它所指向的对象”的拥有者。auto_ptr是一种智能指针(Smart Poiner)。主要用于防止“在当程序抛出异常的时候,发生资源泄漏”问题的发生。

auto_ptr的表现如下:当auto_ptr的生命周期结束的时候,那么它指向的对象也会被delete。

 

语法:
std::auto_ptr<ClassName> ptr(new ClassName());

 

需要:
#include <memory>

auto_ptr的接口定义得非常好,可以像使用其他指针一样来使用它,因为它提供了operator *和operator ->,operator *可以用来提取指针所指向的对象,而operator ->可以访问指针所指向对象的数据成员。但是auto_ptr并没有给出operator ++的运算,这正是为什么C++的某些使用中更多推荐使用引用,而不是指针的原因了。

 

注意:
不能像使用一般指针一样为Smart Pointer赋值。

Like This:
std::auto_ptr<ClassName> ptr(new ClassName());    //OK, Constructor Make It So
std::auto_ptr<ClassName> ptr = new ClassName();   //Error!

 

vc7.1 auto_ptr 的源码:

template <class _Ty>
class auto_ptr;

template <class _Ty>
struct auto_ptr_ref
{
    // proxy reference for auto_ptr copying
    auto_ptr_ref(auto_ptr<_Ty>& _Right) : _Ref(_Right)
    {// construct from compatible auto_ptr
    }
    auto_ptr<_Ty>& _Ref;    // reference to constructor argument
};

template <class _Ty>
class auto_ptr
{// wrap an object pointer to ensure destruction
public:
    typedef _Ty element_type;
    explicit auto_ptr(_Ty*_Ptr = 0) _THROW0() : _Myptr(_Ptr)
    {// construct from object pointer }
    auto_ptr(auto_ptr<_Ty>& _Right) _THROW0() : _Myptr(_Right.release())
    {// construct by assuming pointer from _Right auto_ptr }
    auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0() : _Myptr(_Right._Ref.release())
    {// construct by assuming pointer from _Right auto_ptr_ref }

    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_ptr
            return (auto_ptr_ref<_Other>(*this));
        }
    template <class _Other>
        auto_ptr<_Ty>& 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 }

    template <class _Ty>
        auto_ptr<_Ty>& operator = (auto_ptr<_Ty>& _Right) _THROW0()
        { //Assign Compatible _Right(assume pointer)
            reset(_Right.release());
            return (*this);
        }

    template <class _Ty>
        auto_ptr<_Ty>& operator = (auto_ptr_ref<_Ty>& _Right)_THROW0()
        {//Assign Compatible _Right._Ref(assume pointer)
            reset(_Right._ref.release());
            return (*this);
        }

    ~auto_ptr() { delete Myptr; }    //Destroy The Object.

_Ty& operator*() const _THROW0()
    {// return designated value
        return (*_Myptr);

}

_Ty *operator->() const _THROW0()
    {// return pointer to class object
        return (&**this);

}

_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

};

//[Code End~]

 


   

剖析:
1.关于两个运算符的重载
operator ->会调用到operator *的重载。
return (&**this);看起来很让人费解,是这样的,
假设:
auto_ptr<ClassName> myPtr(new ClassName());
myPtr->member;       //Call Like This. or{myPtr->memFunc();}
所以:
*this == myPtr;
**this == *myPtr == *_Myptr    //Call operator *
&**this == _Myptr

所以你也可以这样修改基类代码,如是修改:
    _Ty* operator->() const _THROW0()
    {// return pointer to class object
        return (&**this);    //return (_Myptr);
    }
这样的修改可能会带来其他的隐含错误,只是现在还没有看出来。

 

2.关于release()和reset()
release()成员函数
auto_ptr将会放弃先前所指向的对象(资源)所有权,然后返回那个对象的指针,若没有任何拥有,则返回NULL指针。
reset()成员函数
默认参数为0;即使不设置参数,或者会使得auto_ptr对象放弃任何对象并删除先前拥有的对象资源。
若是传入新的指针(不包括先前拥有的对象指针),auto_ptr会delete先前拥有的对象,并拥有新的对象。
若是传入该auto_ptr已经拥有的对象,则调用不会产生任何变化。
注意:不要将new[]生成的对象指针数组传入,如果需要使用数组,应该考虑STL的容器们。

 

3.其析构函数就表明了该智能指针的效用来源
auto_ptr对象在析构的时候,也就是其生命周期将尽的时候会自动释放它拥有的对象资源。


注意:
auto_ptr作为参数的传参问题以及其他:
1.若某个函数是此指针的传递终点,那么auto_ptr,所指的是经过传递得到拥有权的auto_ptr,它将会在函数返回的时候被删除,就是在退栈的时候,它的拥有也被删除了。
2.作为某一个函数的返回值的时候,auto_ptr被传递给到一个新的函数中,它的历程就刚刚开始了。
3.即使有异常被抛出,auto_ptr也会尽职地删除它拥有的数据。
4.不要把auto_ptr作为标准容器的元素,因为在某些动作中原有的指针会交出拥有权。

More Resources:

C++深度探索系列:智能指针(Smart Pointer) [一] 

http://dev.csdn.net/develop/article/17/17530.shtm

 原文地址 http://www.cppblog.com/Galaxy/archive/2007/04/16/22011.html
原创粉丝点击