2

我今天读到你不应该为 auto_ptr 使用 STL 容器,因为 auto_ptr 在 = 运算符中删除了它的 rhs 值。

所以我有两个问题:

1)这是否意味着所有具有这种行为的类都不应该在容器中使用?

2)你可以使用什么样的容器?

4

3 回答 3

3

1)这是否意味着所有具有这种行为的类都不应该在容器中使用?

确实是的,因为这不是正确的复制行为,因为之后的副本不等于源,而是破坏了源。这是 C++11 之前移动语义的一种破碎实现,这是std::auto_ptr.

2)你可以使用什么样的容器?

真正的答案实际上是,具有这种行为的类(复制构造函数/赋值破坏其源)不应该存在。幸运的是,现在不再需要这个了,因为 C++11 具有适当的移动语义,可以准确地实现这种破坏性复制,但以安全的方式(简单地说,只有当源真的不再需要时)。

因此std::auto_ptr已弃用,不应再使用。它已被替换std::unique_ptr为可移动但不可复制。但是由于 C++11 容器宁愿移动它们的元素而不是在适当的时候复制,所以 astd::unique_ptr可以完美地在标准容器中使用。您只是不能复制容器或用需要std::unique_ptrs 副本的单个对象填充它,但是这些操作无论如何都不应该起作用,因为它们在概念上对于唯一所有权语义是错误的。

附带说明一下,如果您实际上是std:auto_ptr出于某种原因选择的,那就是您想要唯一的所有权语义,那么 a std::shared_ptr(正如其他答案所建议的)是完全错误的,因为它表现出共享所有权。std::unique_ptr是今天的std::auto_ptr。永远不要垃圾邮件std::shared_ptrs where std::unique_ptrs (甚至是原始指针,但根据您的问题,我排除了该选项)是合适的。

于 2012-09-13T08:49:36.113 回答
2

自动指针有一个非常严格的所有权:它并且只有它负责它所指向的对象的生命周期。如果您复制一个auto_ptr,您将失去对它所指向的内容的引用。

问题在于 STL 容器的工作方式。例如,当您添加一个元素时,容器可能会扩展以获得更多内存,这会导致将所有值复制到新内存中,这本身会导致丢失 auto_ptrs。

认为关联容器在分配额外内存时可能不会完全复制自己,但我绝对不确定,如果有人可以确认,请发表评论,或者只是编辑我的答案。无论如何,你最好不要冒险。

另请注意,Auto_ptr自 C++0x 以来已弃用,建议unique_ptr改用。在您的情况下,std::shared_ptr可能会成功,除非您确实需要您的这些对象的唯一所有权。

于 2012-09-13T08:18:49.177 回答
2

确切地。通常,序列容器元素必须是 CopyConstructible 和 Assignable。这意味着他们需要:

  • 公共复制构造函数
  • 公共赋值运算符

关联容器(set<> 和 map<>)也必须提供严格的弱排序,即operator <必须定义(或专用的比较函数)。

C++ 标准的第 23.1 章提供了详细的要求。

于 2012-09-13T08:21:16.637 回答