网上有很多关于auto_ptr的说法,只要用来解决的问题是new和delete使用不当,导致的内存泄漏问题。
原理: 变量在栈中的生命周期,当退出栈的时候,变量会被释放,也就是对象的析构函数会被执行。可以说是在原始对象基础上再封装一层,上层来负责delete。
一个简单的例子
#include <iostream>
#include <memory>
using namespace std;
class TC
{
public:
TC(){cout<<"TC()"<<endl;}
~TC(){cout<<"~TC()"<<endl;}
void print() {
cout<<num<<endl;
}
int num;
};
void test()
{
auto_ptr<TC> pTC(new TC);
}
int main()
{
test();
return 0;
}
输出结果为
TC()
~TC()
很简单是不是,关于auto_ptr的很多弱点,网上有很多说法,我想更正的一点是auto_ptr最好不要用=号复制,否则就不能用原来的指针了,因为这是所有权转移导致的,这话放到VC6.0就是错的,VS2008则是对的,因为memory.h的版本不同
VC6.0的头文件路径为:C:\Program Files\Microsoft Visual Studio\VC98\Include\MEMORY
VS2008头文件路劲为:C:\Program Files\Microsoft Visual Studio 9.0\VC\include
VC6.0是如何实现的,看源码:
template<class _Ty>
class auto_ptr {
public:
typedef _Ty element_type;
explicit auto_ptr(_Ty *_P = 0) _THROW0()
: _Owns(_P != 0), _Ptr(_P) {}
auto_ptr(const auto_ptr<_Ty>& _Y) _THROW0()
: _Owns(_Y._Owns), _Ptr(_Y.release()) {}
auto_ptr<_Ty>& operator=(const auto_ptr<_Ty>& _Y) _THROW0()
{if (this != &_Y)
{if (_Ptr != _Y.get())
{if (_Owns)
delete _Ptr;
_Owns = _Y._Owns; }
else if (_Y._Owns)
_Owns = true;
_Ptr = _Y.release(); }
return (*this); }
~auto_ptr()
{if (_Owns)
delete _Ptr; }
_Ty& operator*() const _THROW0()
{return (*get()); }
_Ty *operator->() const _THROW0()
{return (get()); }
_Ty *get() const _THROW0()
{return (_Ptr); }
_Ty *release() const _THROW0()
{((auto_ptr<_Ty> *)this)->_Owns = false;
return (_Ptr); }
private:
bool _Owns;
_Ty *_Ptr;
};
很显然,VC6.0并没有权限转移一说,auto_ptr<_Ty>& operator=函数,只是引用别人的副本,通过_Owns变量来控制delete的,当使用复制时,会把上个对象的_Owns置为false,仔细看代码就能发现。release就是改变_Owns的值。
所以完全可以使用复制而不用担心权限转移导致的引用对象为空的问题
那么VS2008又是怎么搞的:
template<class _Other>
auto_ptr<_Ty>& operator=(auto_ptr<_Other>& _Right) _THROW0()
{ // assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
}
_Ty *release() _THROW0()
{ // return wrapped pointer and give up ownership
_Ty *_Tmp = _Myptr;
_Myptr = 0;
return (_Tmp);
}
明显这里就有权限转移的说法了,因为复制的时候会把上一个对象应用清空。
至于微软为何如此做,我倒不是很清楚,我能理解的是规范标准吧,智能指针这一块,看用的人懂多少,不是说这不好那不好什么的,重点看使用场景和使用者