【问题标题】:Why does std::auto_ptr operator = trash objects?为什么 std::auto_ptr operator = 垃圾对象?
【发布时间】:2009-01-09 06:50:58
【问题描述】:

std::auto_ptr 和赋值似乎有问题,以至于引用的对象似乎由于某种原因被丢弃了。

std::auto_ptr<AClass> someVar = new AClass();  // should work, but mangles content
std::auto_ptr<AClass> someVar( new AClass() ); // works fine.
std::auto_ptr<AClass> someVar = std::auto_ptr<AClass>(new AClass()); // works fine.

std::auto_ptr<AClass> someVar;
someVar.reset( new AClass() ); // works fine.

我已经对其进行了跟踪,并且(通过观察调试器中的值)似乎问题发生在从临时 std::auto_ptr_byref() 传输指针时,该临时 std::auto_ptr_byref() 是为包装 rhs 指针而创建的。也就是说进入auto_ptr(auto_ptr_ref<_ty>_Right)函数时_Right中的值是正确的,但是离开时_Myptr中的值是垃圾。

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

    void *_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 **_Pptr = (_Ty **)_Right._Ref;
    _Ty *_Ptr = *_Pptr;
    *_Pptr = 0; // release old
    _Myptr = _Ptr;  // reset this
    }
auto_ptr<_Ty>& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()
{   // assign compatible _Right._Ref (assume pointer)
_Ty **_Pptr = (_Ty **)_Right._Ref;
_Ty *_Ptr = *_Pptr;
*_Pptr = 0; // release old
reset(_Ptr);    // set new
return (*this);
}

一开始我以为这是搞砸了继承和切掉接口,然而即使这个类只有一个父类也会发生这种情况。

如果我们记得的话,我们可以避免使用 = new,方法是使用方括号或更改为在 rhs 上具有显式 std::auto_ptr temp,这当然容易出错。

只是这个版本的库被破坏了,还是我没有得到一些底层的东西?

我们还注意到了将 std::auto_ptr 分配给 boot::shared_ptr 的类似问题,尽管我们现在完全删除了它,我不记得是哪种语法导致了这个问题。

【问题讨论】:

  • 您使用的是什么编译器和版本?
  • 请参阅stackoverflow.com/questions/372665/…,了解关于第一行和第二行之间差异的一些讨论。
  • 这很有趣,但没有直接帮助解决问题
  • 我不知道你的情况,但如果可能的话,我建议重构使用 boost/TR1 智能指针。 auto_ptr 难以使用和推理,例如不能存储在 STL 容器中。

标签: c++ memory std


【解决方案1】:

第一行:

std::auto_ptr<AClass> someVar = new AClass();  // should work, but mangles content

应该会导致编译器错误。因为没有从原始AClass 指针到auto_ptr 的隐式转换(采用原始指针的auto_ptr 的构造函数标记为explicit),因此不允许使用“复制初始化程序”形式进行初始化。

VC9 报错:

C:\temp\test.cpp(23) : error C2440: 'initializing' : cannot convert from 'AClass *' to 'std::auto_ptr<_Ty>'

我尝试过的其他编译器(GCC 3.4.5、Comeau C/C++ 4.3.10.1、Digital Mars)给出了类似的错误。

编辑:

看起来这实际上是 VS2005 实现 auto_ptr&lt;&gt; 中的一个错误(不确定它是在 SP1 中引入还是从一开始就在 VS2005 中)在 VS2008 中得到修复。这是该问题的 MS Connect 错误记录:

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842&wa=wsignin1.0

【讨论】:

  • 第一行与operator=()无关;这是一个初始化,而不是一个赋值。有一个接受 auto_ptr 的 ctor 和一个接受原始指针的 ctor。原始指针 ctor 是显式的,因此没有从原始指针到 auto_ptr 的转换。
  • @wilhelmtell - 你是对的。我在你指出的同一时间修正了这个错误陈述。
  • 虽然一种优化是调用 ctor 并进行初始化,但它并没有这样做。在 MSVC 2005 中,库中引入了 auto_ptr_ref,而是将其构建为临时 rhs。在以前的版本中,我无法执行第 1 行,是的,我曾经遇到过该错误。
  • 正如现在从 MSVC8 库中提供的 文件的副本中显示的那样,原始 ptr 是显式的,但是 auto_ptr_ref 不是显式的,auto_ptr_ref 的构造函数也不是显式的。 :( 图书馆的变化是最大的痛苦!
  • 您的链接略有损坏。 (我没有足够的代表来修复它。)
【解决方案2】:

【讨论】:

    【解决方案3】:

    编辑:Michael 说的很对,这是一个编译错误,那么你使用的是哪个编译器?您需要调用 reset 将新值放入 auto_ptr。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多