【问题标题】:STL containers and non copyable (and non movable) objectsSTL 容器和不可复制(和不可移动)的对象
【发布时间】:2013-04-08 18:03:03
【问题描述】:

由于 STL 容器要求所有内容都是可复制和可分配的,那么在处理不可复制对象时,首选的习惯用法是什么?

我可以想到两种不同的方法:

  1. 存储(智能)指针而不是 STL 容器中的对象。

  2. 摆脱 STL 容器并实现我自己的列表(例如,每个对象都必须包含指向下一个对象的指针)。

第二种方法的主要缺点是析构函数的实现(是否应该以递归方式在当前对象之前销毁“下一个”对象?)

【问题讨论】:

  • 当然这取决于具体情况,但我通常会投票 1),如果只是因为出错的可能性较小。当然,您确实会失去诸如std::vector 的缓存友好性之类的东西...
  • Boost Intrusive 是 2) 的实现
  • Since STL containers require that all contents be copyable and assignable 我认为现在可移动性已经足够了?假设您真的是指标准库。
  • @BoBTFish 这看起来像是我的答案
  • “由于 STL 容器要求所有内容都是可复制和可分配的” - 不,它们不需要(如果您指的是最新的 C++ 标准库)。

标签: c++ stl


【解决方案1】:

由于 STL 容器要求所有内容都是可复制和可分配的,那么在处理不可复制对象时首选的习惯用法是什么?

嗯,实际上在 C++11 中,它们要求对象是可移动的。由于emplace_* 方法,只有某些操作需要它们是可分配的。

我可以想到两种不同的方法:

  1. 存储(智能)指针而不是 STL 容器中的对象。

  2. 摆脱 STL 容器并实现我自己的列表(例如,每个对象都必须包含指向下一个对象的指针)。

这两种方法当然是可行的。

在 C++11 中,带有 std::unique_ptr<YourObject> 元素的 STL 容器可能是最佳选择。从头到尾都是标准的。基于节点的容器可能存在轻微性能问题,因为节点和它们指向的元素将是不同的内存区域;但它通常是难以察觉的。

如果它是可感知的,或者如果你不能使用 C++11,那么你应该了解侵入式容器,它包括用钩子增加你的对象,以便它们可以将自己排列成列表,例如。显然有一个 Boost 库:Boost.Intrusive

你说的不可移动?

我会诚实地挑战大多数认为不应移动对象的设计。移动的唯一问题与对象身份有关,以及使指向被移动对象的指针无效的潜在问题(从而使悬空指针处于后面)。这通常可以通过智能指针和/或工厂方法来解决。

【讨论】:

    【解决方案2】:

    我会选择方法 #1:即在 STL 容器中存储 smart 指向对象的指针。

    请注意,在 STL 容器中存储非拥有的原始指针是可以的(例如 observing 原始指针),但存储 拥有 原始指针是一种“泄漏":改用 shared_ptr 或新的 C++11 的 unique_ptr

    至于 #2,从头开始编写自己的容器需要大量时间和精力,而且我相信您无法在合理的时间范围内与完整的商业质量 STL 库实现的丰富性相提并论。

    【讨论】:

    • 我希望对“泄漏性”这个术语进行更多解释。你的意思是安全吗?
    • 好吧,我不是说要实现我自己的容器。我的意思是“以 C 方式”实现我自己的链表。无论如何,第一种方法似乎更好。
    • @user1916893:这意味着你必须非常小心地使用它以避免内存泄漏。您必须记住原始指针拥有对象,简单地删除或替换它们会泄漏拥有的对象。智能指针以编译器可以检查的方式显式管理所有权;如果没有有意识的努力,很难泄漏。
    • 除了@MikeSeymour 的明智注释之外,拥有原始指针也存在异常安全的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    • 2016-01-10
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 2014-04-13
    相关资源
    最近更新 更多