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

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

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. 

为了克服这个限制,如果你没有C ++ 11,你应该使用std::unique_ptrstd::shared_ptr或者std::weak_ptr智能指针或者增强等价物。 这里是这些智能指针的boost库文档。

auto_ptr复制语义与容器不兼容。

特别是,将一个auto_ptr复制到另一个auto_ptr不会创build两个相等的对象,因为已经失去了指针的所有权。

更具体地说,复制auto_ptr会导致其中一个副本放开指针。 这些遗留在容器中的哪一个没有被定义。 因此,如果将auto_ptrs存储在容器中,则可以随机失去对指针的访问权限。

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

  • 智能指针 – 什么,为什么,哪个?
  • 本周导师#25

STL容器需要能够复制存储在其中的项目,并且旨在期望原始文件和副本等同。 自动指针对象具有完全不同的契约,由此复制创build所有权的转移。 这意味着auto_ptr的容器会根据使用情况显示奇怪的行为。

有效的STL(Scott Meyers)第8项中可能出错的详细描述,以及Effective C ++(Scott Meyers)第13项中不太详细的描述。

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

C ++ 03标准(ISO-IEC 14882-2003)在第20.4.5段中说:

[…] [ 注意:auto_ptr不符合标准库容器元素的CopyConstructible和Assignable要求,因此使用auto_ptr实例化标准库容器会导致未定义的行为。 – 结束注意 ]

C ++ 11标准(ISO-IEC 14882-2011)在附录D.10.1第3段中说:

[…] 注意:auto_ptr的实例满足MoveConstructible和MoveAssignable的要求,但不符合CopyConstructible和CopyAssignable的要求。 – 结束注意]

C ++ 14标准(ISO-IEC 14882-2014)在附录C.4.2中说附录D:兼容性特性:

更改 :类模板auto_ptr,unary_function和binary_function,函数模板random_shuffle以及函数模板(及其返回types)ptr_fun,mem_fun,mem_fun_ref,bind1st和bind2nd未定义。
理由 :被新function所取代。
对原始function的影响 :使用这些类模板和function模板的有效C ++ 2014代码可能无法在本标准中编译。

无论如何,由于const的正确性,你不能把auto_ptr对象放到std :: vector中。 你应该得到一个编译错误。