vs2005里auto_ptr的指针赋值一个陷阱

来源:互联网 发布:人的音域 知乎 编辑:程序博客网 时间:2024/05/01 02:10

先来一段代码:

#include <memory>#include <atlbase.h>class A{public:A() : ma(0) {}void print() {ATLTRACE(_T("%d"), ma);}private:int ma;};int _tmain(int argc, _TCHAR* argv[]){std::auto_ptr<A> aPtr = new A();aPtr->print();return 0;}
Debug运行这段代码的时候,直接报错,提示aPtr不可以解引用。

看了好几遍,感觉好像没什么问题,找不到头绪。 没办法,一步步的跟进去调试看到底在哪里出的事。

跟到auto_ptr的构造函数,才发现它调用的构造函数不对,上述代码调用的构造函数如下:

auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0(){// construct by assuming pointer from _Right auto_ptr_ref_Ty **_Pptr = (_Ty **)_Right._Ref;_Ty *_Ptr = *_Pptr;*_Pptr = 0;// release old_Myptr = _Ptr;// reset this}
auto_ptr_ref是一个proxy类,它接受void*类型的指针参数,代码如下:

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

这说明,new运算符返回的指针类型是个void*,问题极有可能出上述auto_ptr构造函数里面。

auto_ptr_ref的_Ref持有了new出对象的指针,而在上述auto_ptr构造函数中,把它当作了A**来使用,并解引用了一次来获取A*。

很明显,这一次解引用导致auto_ptr中指针取到的值是0。

同时,下面的代码也没有调用到正确的构造函数,它调用的构造函数跟上面的是一样的:

A a;std::auto_ptr<A> aPtr = &a;aPtr->print();

auto_ptr的指针转换构造函数带了explicit关键字,除非写成 aPtr(&a)。可以用下面的例子说明这两者之间的区别:

class B{public:explicit B(A* pa) : ma(pa) { }B(void* p) : ma(0) {}private:A* ma;};int _tmain(int argc, _TCHAR* argv[]){A a;B b = &a;return 0;}
上面调用的是B(void*)这个构造函数,如果把explicit去掉,调用的是B(A*)这个构造函数。




0 0
原创粉丝点击