1

我知道许多关于避免堆碎片的文章。我的问题与我们使用向量存储数据时发生的具体情况有关:

class foo{
public:
std::vector<bar>; // Or I can have std::vector<bar*>
};

我使用 new 或 delete 没有问题(我没有内存泄漏,当不使用 bar 时我很清楚,我可以在必要时调用 delete)。但是关于堆碎片,哪个更好?这是否使堆栈溢出的可能性更大?

编辑:我实际上没有任何新信息要添加。我只是想感谢大家,并说我发现任何带有 C++ 标记的问题似乎都会吸引这么多知识渊博的乐于助人的人。它真的很不错。谢谢你。

4

4 回答 4

2

TL;DR,除非你有充分的理由,通过可靠的测量,总是喜欢使用vector带值类型。

我会为std::vector<bar>形式辩护。除非您有其他(测量的)原因,否则具有vector值类型的保证连续内存是一个更好的主意。当向量分配一个连续的内存块时,对象将在内存中彼此相邻布置(有一些保留)。这使主机系统和运行时有更好的机会避免碎片。单独分配对象可能会导致碎片,因为您无法控制它们的分配位置。

我注意到您对堆栈的担忧;vector有一个小的堆栈分配,所以这不应该是一个问题,“通常的”分配器std::allocator用来为堆上new的分配内存。vector

为什么vector总是要受青睐?Herb Sutter 对此进行了详细介绍;http://channel9.msdn.com/Events/Build/2014/2-661从 23:30 左右开始提供支持图表、图表、解释等,他在 46:00 左右拿起 Bjarne 的材料。

于 2014-07-10T08:04:25.497 回答
1

OP 似乎对它的作用有一个基本的误解std::vector:它在堆上分配一个连续的内存块,使用时你不需要担心你的堆栈空间vector!因此,当您真的不需要存储任何东西但它们自己的对象时,只需将它们放入您的vector,您就可以了。

所以std::vector<bar>在你的情况下似乎是正确的选择。另外,不要过早地担心堆碎片,让编译器担心。(但是您应该担心提供预取器,这就是为什么std::vector<bar>应该是您存储任何东西的标准选择。)

于 2014-07-10T08:21:30.620 回答
1

在以下情况下使用指针向量:

  • Bar 是一个基类,您希望将派生类的实例存储在向量中。
  • Bar 没有适当的复制/移动构造函数,或者它非常昂贵
  • 您希望将指向向量中对象的指针存储在其他地方,并且您可能会更改向量的容量(例如,由于调整大小或 push_back)。如果对象是按值存储的,那么当容量变化时,旧的指针就会失效。
  • 您希望向量中的某些元素是“空的”(可以用空指针表示),并且将虚拟的、未使用的 Bar 实例按值存储在向量中是不切实际的。

如果您确实需要指针,我强烈建议您使用智能指针。

在其他情况下,您应该更喜欢按值存储对象,因为它通常更有效。

于 2014-07-10T10:23:52.567 回答
1

保证它的std::vector内容将存储在连续内存中。如果您将对象存储在向量中,那么每个对象将在一大块内存中彼此相邻,但是如果您将指向向量的指针指向使用 创建的对象new,那么每个对象将位于内存中的随机位置.

所以第一个版本(存储对象,而不是指针)对于避免堆碎片和利用缓存都更好。

于 2014-07-10T08:01:42.283 回答