本文讲述关于auto_ptr智能指针赋值时一个古怪的现象。
1.为何要使用智能指针
void fun()
{
char* p = new char;
delete p;
}
在动态分配一个内存时,需要使用delete来手动释放掉,若忘记释放掉内存就会造成内存的泄露。所以为了优雅的解决这个问题,智能指针就出现了。
2.auto_ptr 智能指针赋值操作
int getIndex()
{
struct pack{
char name[MAX_PATH];
int index;
};
std::auto_ptr<pack> test1(new pack);
test1.index = 1;
std::auto_ptr<pack> test2(test1);
return test1.index;
}
好了,我们看上面的代码好像一切都是正常是吧,来我们试试运行的结果如何。额~,程序出现崩溃,查看错误test1已经变为空指针了,哈哈,古怪的想象就这样出现了。别再盯着这部分的代码了,你从这里是看不出这个现象出现的原因的,为了弄清这个古怪的现象我翻出了auto_ptr智能指针的源码。
3.auto_ptr赋值操作产生古怪现象的原因
template<class _Ty>
class auto_ptr
{ // wrap an object pointer to ensure destruction
auto_ptr(_Myt& _Right) _THROW0()
: _Myptr(_Right.release())
{ // construct by assuming pointer from _Right auto_ptr
}
_Ty *release() _THROW0()
{ // return wrapped pointer and give up ownership
_Ty *_Tmp = _Myptr;
_Myptr = 0;
return (_Tmp);
}
}
从auto_ptr的拷贝构造函数中我们可以看出,在被拷贝对象拷贝到对象中时,被拷贝对象会先调用release函数释放掉自己的指针,将其设置为0,看到这里我们就可以清楚了为什么赋值时会产生这样古怪的想象了吧。
想想它为什么会这样做呢,其实很容易能想到,我们在赋值时如不将被拷贝的对象设置为0,就会出现这两个智能指针在调用析构函数时都会释放相同的堆内存,对同一个堆内存delete两遍造成的问题可以想象得到。
好了,我们既知道了这样使用auto_ptr智能指针会造成这样的问题,还有它为何需要这样做,那我们就应该在使用它时规避掉这样的风险。特别提一句,尽量不要在vector等容器中使用auto_ptr智能指针,因为在容器中所知道的排序函数就有赋值操作,会造成容器中一部分元素为空。