【问题标题】:Considerations when choosing between storing values vs pointers in std:: containers在 std:: 容器中存储值与指针之间进行选择时的注意事项
【发布时间】:2017-03-15 22:48:56
【问题描述】:

在标准集合中存储对象时,在决定存储值还是存储指针时应该考虑哪些因素?这些集合的所有者(ObjectOwner)在堆上分配。对于小型结构/对象,我一直在存储值,而对于大型对象,我一直在存储指针。我的理由是,当标准容器调整大小时,它们的内容会被复制(小副本好,大副本坏)。这里还有什么要记住的吗?

class ObjectOwner
{
   public:
     SmallObject& getSmallObject(int smallObjectId);
     HugeObject* getHugeObject(int hugeObjectId);

   private:
     std::map<int, SmallObject> mSmallObjectMap; 
     std::map<int, HugeObject *> mHugeObjectMap; 
};

编辑:

上面的示例以获得更多上下文:

  • 相对不频繁地创建/删除存储在 std::map 中的项目(每秒几次)
  • 经常从 std::map 获取(每 10 毫秒一次)
  • 小对象:
  • 巨大的对象:> 1024 字节

【问题讨论】:

  • “我的理由是,当标准容器调整大小时,它们的内容会被复制”——取决于容器。完全没有这个要求;事实上,对于大多数容器来说这是错误的
  • “这里还有什么要记住的吗?”如果可以的话,使用智能指针而不是原始指针
  • @UKMonkey 确实,在大多数容器中调整大小不是问题,但破坏和构造才是问题,这对大型对象来说代价高昂。
  • @imreal 你必须构造和破坏对象,不是吗?
  • @imreal 正如 UKMonkey 所说,一个解决方案是使用智能指针:shared_ptr 允许共享对象的属性,或 unique_ptr 用于独占属性

标签: c++


【解决方案1】:

除非我通过指针需要它,否则我会按值存储对象。可能的原因:

  • 我需要将对象层次结构存储在容器中(以避免切片)
  • 我需要共享所有权

可能还有其他原因,但按大小推理仅对某些容器有效(例如std::vector),即使在那里您也可以将对象移动成本降至最低(例如提前预留足够的空间)。您以std::map 举例说明对象大小没有任何意义,因为std::map 在增长时不会重新定位对象。

注意:方法的返回类型不应反映您将其存储在容器中的方式,而应基于方法语义,即如果找不到对象,您将做什么。

【讨论】:

【解决方案2】:

只有您的分析员知道您的具体案例的答案;尝试使用指针而不是对象是在必须完成复制时最小化复制量的可靠方法(无论是调整向量的大小还是整个容器的副本);但有时您想要该副本,因为它是互斥锁内线程的快照,并且复制容器比保存互斥锁和处理数据要快。

某些对象可能无法以指针以外的任何方式保存,因为它们不可复制。

使用指针容器带来的任何性能提升都可能被编写更多复制代码或重复调用 new() 的成本所抵消。

没有一个适合所有人的答案,在您担心这里的性能之前,您应该确定性能问题的真正所在。 (只是重复这一点 - 使用分析器!)

【讨论】:

    猜你喜欢
    • 2016-03-26
    • 2023-04-09
    • 2011-04-23
    • 2010-09-06
    • 2018-08-13
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多