在std::容器中选择存储值还是存储指针时的注意事项

Considerations when choosing between storing values vs pointers in std:: containers

本文关键字:存储 指针 注意事项 选择 std      更新时间:2023-10-16

在标准集合中存储对象时,在决定是存储值还是存储指针时应该考虑哪些因素?在堆上分配这些集合的所有者(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毫秒一次)
  • 小对象:<32个字节
  • 巨大的对象:> 1024字节

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

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

可能还有其他原因,但根据大小进行推理只适用于某些容器(例如std::vector),即使在这些容器中,您也可以使对象移动成本最小化(例如提前预留足够的空间)。你的std::map对象大小的例子没有任何意义,因为std::map在增长时不会重新定位对象。

注意:方法的返回类型不应该反映你在容器中存储它的方式,而是应该基于方法语义,即如果找不到对象你会怎么做

只有你的分析器知道你的具体情况的答案;尝试使用指针而不是对象是一种可靠的方法,可以在必须进行复制时(无论是矢量的大小调整还是整个容器的复制)最大限度地减少复制量;但有时你需要复制,因为它是互斥锁内线程的快照,复制容器比保存互斥锁并处理数据要快得多。

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

使用指针容器所获得的任何性能增益都可能被必须编写更多复制代码或重复调用new()的成本所抵消。

没有一个答案是放之四海而皆准的,在您担心性能问题之前,您应该确定性能问题的真正所在。(只是重复一点——使用分析器!)