为什么将std::auto_ptr<>
与标准容器一起使用是错误的?
答案 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_ptr
,std::shared_ptr
或std::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代码可能无法在此编译 国际标准。