正确使用std::auto_ptr
2014-07-07 22:40
323 查看
转自:http://blog.csdn.net/just_a_beginning/article/details/4386755
这里面的实例,很好。可以参考auto_ptr源码
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).
这里面的实例,很好。可以参考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).
相关文章推荐
- 正确使用std::auto_ptr
- 正确使用 std::auto_ptr 智能指针
- 正确使用std::auto_ptr
- 正确使用std::auto_ptr
- 正确使用std::auto_ptr
- std::auto_ptr的使用方法
- 【VS开发】【C++开发】正确使用auto_ptr智能指针
- std::auto_ptr的原理及使用
- 正确使用std::auto_ptr http://blog.csdn.net/just_a_beginning/article/details/4386755
- 使用auto_ptr需要注意的事项
- 剖析C++标准库智能指针(std::auto_ptr)
- 智能指针auto_ptr使用注意事项
- 剖析C++标准库智能指针(std::auto_ptr)
- 智能指针 std::auto_ptr 和 shared_ptr
- 使用auto_ptr需要注意的事项
- auto_ptr的使用误区
- Smart Pointers - What, Why, Which?- std::auto_ptr
- [经验总结]auto_ptr使用小结
- std::auto_ptr 不能赋值 简析
- auto_ptr 的学习和使用