222

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

4

6 回答 6

125

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或智能指针或 boost 等效项。这是这些智能指针的 boost 库文档。std::weak_ptr

于 2008-09-21T17:47:35.863 回答
66

复制语义auto_ptr容器不兼容。

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

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

于 2008-09-21T17:29:13.987 回答
39

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

于 2010-06-25T19:01:08.453 回答
17

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

在 Effective STL (Scott Meyers) 第 8 条中有详细描述可能出错的地方,在 Effective C++ (Scott Meyers) 第 13 条中也有不太详细的描述。

于 2008-09-21T17:40:43.680 回答
12

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

于 2008-09-21T17:44:30.380 回答
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 代码可能无法在本国际标准中编译。

于 2012-10-30T14:30:30.003 回答