您的位置:首页 > 其它

正确使用std::auto_ptr

2014-07-07 22:40 323 查看
转自:http://blog.csdn.net/just_a_beginning/article/details/4386755

这里面的实例,很好。可以参考auto_ptr源码

// TEMPLATE CLASS auto_ptr
template<class _Ty>
class auto_ptr;

template<class _Ty>
struct auto_ptr_ref
{	// proxy reference for auto_ptr copying
explicit auto_ptr_ref(_Ty *_Right)
: _Ref(_Right)
{	// construct from generic pointer to auto_ptr ptr
}

_Ty *_Ref;	// generic pointer to auto_ptr ptr
};

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()
{	// 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>
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
}

auto_ptr<_Ty>& operator=(auto_ptr<_Ty>& _Right) _THROW0()
{	// assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
}

auto_ptr<_Ty>& 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
if (_Myptr != 0)
delete _Myptr;
}

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

#if _HAS_ITERATOR_DEBUGGING
if (_Myptr == 0)
_DEBUG_ERROR("auto_ptr not dereferencable");
#endif /* _HAS_ITERATOR_DEBUGGING */

__analysis_assume(_Myptr);

return (*get());
}

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

#if _HAS_ITERATOR_DEBUGGING
if (_Myptr == 0)
_DEBUG_ERROR("auto_ptr not dereferencable");
#endif /* _HAS_ITERATOR_DEBUGGING */

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 && _Myptr != 0)
delete _Myptr;
_Myptr = _Ptr;
}

private:
_Ty *_Myptr;	// the wrapped object pointer
};


1, auto_ptr类

auto_ptr是一个模板类,定义如下:

template <typenameType>

class
auto_ptr {...};

它存储的是一个指向Type的指针。

顾名思义,auto_ptr是一种智能指针,它包含一个动态分配内存的指针,并在它生命周期结束的时候,销毁包含的指针所指向的内存。

例1:

void f()

{

Type* pt(new Type);

//一些代码...

delete pt;

}

这样的代码很常见,但它有可能造成内存泄露。首先你用了new,你就要记得用delete,但即使你记住了用delete,还是会出问题。如果f()在执行delete pt之前,就抛出了异常,函数返回了。那么这个分配的对象就没被删除。

使用auto_ptr,很优雅的解决了这些问题。

例2:

void f()

{

auto_ptr<Type> pt(new Type);

//一些代码...

}

现在的代码,不会泄露Type类型的对象。不管是函数正常结束,还是抛出异常结束,都会调用pt的析构函数,从而删除分配的对象。

2, auto_ptr构造函数

构造函数1:explicitauto_ptr(Type*_Ptr
= 0) throw( );

auto_ptr<int> pt; //包含一个int*的指针,并初始化为NULL

auto_ptr<int> pt(new int(123));//包含一个int*的指针,并初始化为123的地址

auto_ptr<int> pt =new int(123);
//error!构造函数声明为explicit

构造函数2:auto_ptr(auto_ptr<Type>&_Right)
throw( );

int* ptr =new int();

auto_ptr<int> pt1(ptr); //构造函数1

auto_ptr<int> pt2(pt1);//将pt1的使用权转给pt2,注意pt1指向NULL了

//pt1调用了本身的release()函数,将内部指针地址传给pt2

构造函数3:template<typename
Other>

auto_ptr(auto_ptr<Other>&_Right)
throw( );

声明这样一个拷贝构造函数的目的,就是为了派生类指针能转换成基类的指针。

例:

class Base { };

class Derived :public Base { };

auto_ptr<Derived> pDerived(new Derived);

auto_ptr<Base> pBase(pDerived); //让这样的代码能通过编译器

其本质是为了让,auto_ptr类内部的Derived*转换为Base*

构造函数4:auto_ptr(auto_ptr_ref<Type>_Right)
throw( );

//暂略

3, auto_ptr成员函数

成员函数1:Type* get( )const throw( );

获得包含指针的地址

int* ptr = new int(123);

auto_ptr<int> pt(ptr);

assert(pt.get() == ptr); //相等,指向同一地址

成员函数2:Type* release( )throw(
);

返回包含指针的地址,并将包含指针设为NUll

string* pstr = new string("hello");

auto_ptr<string> pt(pstr);

pt.release(); //不在指向string对象

//此时,pt.get()等于NULL

delete pstr; //应该手动删除pstr指向的内存块

成员函数3:void
reset(Type* _Ptr = 0);

double* pdouble1 = new double(3.14);

double* pdouble2 = new double(1.23);

auto_ptr<double> pt1(pdouble1);

pt1.reset(pdouble2); //将删除pt1所指向的内存块就是pdouble1指向的那块

//此时,pt.get()等于pdouble2

cout << *pdouble1; //error,pdouble已经是野指针了。

4, 使用总结

1,auto_ptr存储的指针应该为NULL或者指向动态分配的内存块。

2,auto_ptr存储的指针应该指向单一物件(是new出来的,而不是new[]出来的)。

3,两个auto_ptr对象不会同时指向同一块内存块。要明白2个auto_ptr对象赋值会发生什么。

4,千万不要把auto_ptr对象放在容器中。

5,当将auto_ptr作为函数参数时,最好声明为const auto_ptr<T>&(by const ref).当函数返回值可以简单的传值(by value).
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: