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

时间:2008-09-21 17:27:28

标签: c++ stl raii auto-ptr c++-faq

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

6 个答案:

答案 0 :(得分: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.

要克服此限制,如果您没有C ++ 11,则应使用std::unique_ptrstd::shared_ptrstd::weak_ptr智能指针或增强等效项。 Here is the boost library documentation for these smart pointers.

答案 1 :(得分:65)

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

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

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

答案 2 :(得分:38)

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

答案 3 :(得分:17)

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

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

答案 4 :(得分:12)

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

答案 5 :(得分:4)

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

  

[...]   [注意:[...]   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和   函数模板(及其返回类型)ptr_fun,mem_fun,   mem_fun_ref,bind1st和bind2nd未定义   理由:取代新功能。
  对原始功能的影响:使用这些类模板和函数模板的有效C ++ 2014代码可能无法在此编译   国际标准。