为什么在标准容器中使用std :: auto_ptr <>是错误的?

Uha*_*all 208 c++ stl raii auto-ptr c++-faq

为什么使用std::auto_ptr<>标准容器是错误的?

Kev*_*vin 123

C++标准规定STL元素必须是"可复制的"和"可分配的".换句话说,必须能够分配或复制元素,并且这两个元素在逻辑上是独立的.std::auto_ptr不符合此要求.

以此代码为例:

class X
{
};

std::vector<std::auto_ptr<X> > vecX;
vecX.push_back(new X);

std::auto_ptr<X> pX = vecX[0];  // vecX[0] is assigned NULL.
Run Code Online (Sandbox Code Playgroud)

为了克服这种限制,你应该使用std::unique_ptr,std::shared_ptrstd::weak_ptr智能指针或升压等价物,如果你没有C++ 11. 以下是这些智能指针的boost库文档.

  • 如果您不需要共享所有权,还应该考虑增强指针容器. (7认同)
  • `unique_ptr`也不允许复制,因此除非可以使用其移动语义,否则某些STL操作将无法正常工作. (4认同)
  • "为了克服这个限制,你应该使用`std :: unique_ptr`":由于移动语义(它的规范需要rvalue引用),类模板只能存在,所以它从根本上要求C++ 11.然而(和相关的)C++ 11标准不再说STL元素类型必须是"可复制构造"和"可分配"; 移动可构造和移动可分配的足够.实际上,`unique_ptr`实例只是可移动构造和移动可分配的.但是`auto_ptr`实例也是如此!因此,在C++ 11中,您可以使用`auto_ptr`来执行`unique_ptr`. (4认同)
  • @ratchetfreak:嗯,我不明白。什么?“除非您进行了“重置”和“发布”,否则我的评论中看不到这有什么用。请注意,`auto_ptr`和`unique_ptr`都具有这两种方法,并且在两种情况下它们都执行相同的操作。 (2认同)

Fra*_*ger 65

拷贝语义auto_ptr不与容器兼容.

具体来说,将一个复制auto_ptr到另一个不会创建两个相等的对象,因为一个对象已失去其对指针的所有权.

更具体地说,复制a auto_ptr会导致其中一个副本放开指针.未定义容器中的哪些保留.因此,如果存储auto_ptrs在容器中,则可以随机丢失对指针的访问权限.


Laz*_*zer 38

关于这个主题的两篇超级优秀文章:

  • @DeadMG:是的,你是对的.但这不是我的目的.如果有人在某个时候来到这个帖子并想了解`auto_ptr`和东西,这些链接将会有所帮助,我相信. (26认同)
  • @DeadMG:此问题未作为重复关闭,因此可以进行扩展.拉泽尔说过之前没有说过的话.我猜他是偶然来的. (8认同)
  • @DeadMG:为什么不必要? (3认同)

Gar*_*our 17

STL容器需要能够复制您存储在其中的项目,并且旨在使原始和副本等效.自动指针对象具有完全不同的合同,因此复制会创建所有权转移.这意味着auto_ptr的容器将表现出奇怪的行为,具体取决于使用情况.

详细描述了有效STL(Scott Meyers)第8项中可能出现的问题,以及Effective C++(Scott Meyers)第13项中的不详细描述.


Dus*_*etz 12

STL容器存储包含项的副本.复制auto_ptr时,它会将旧ptr设置为null.许多容器方法都被这种行为打破了.

  • 像任何正确的C++ 11对象一样,@ tracer`unique_ptr`只能在移动构造或分配时转移其资源的所有权,确保程序员必须故意传递`std :: move(sourceObject)`或临时的,而不是而不是传递一个_lvalue_而且不直观地/不可预测地让它被副本赋值变异......正如这里所强调的那样,这是`auto_ptr`的核心问题. (2认同)