【问题标题】:vector of pointers or structs?指针或结构的向量?
【发布时间】:2020-11-02 04:12:51
【问题描述】:

说,我定义了一个名为Node 的结构(或类,没关系)。在 C++ 中,我们可以使用结构向量或指针向量来存储许多 Nodes。

struct Node {...}
void main() {
    std::vector<Node> nodes;
    // or we can write:
    std::vector<Node*> nodes;
}

据我所知,如果我使用结构向量,那么向量需要大内存来存储向量中的每个整个结构。所以我认为指针向量更好。但现在我在想,是否有任何我不知道的语法,或者任何迂回的方法来编写vector&lt;Node&gt;,而不复制向量中的每个结构?或者更好,也许编译器已经为我做了这个优化?

【问题讨论】:

  • 当向量拥有它的对象时,首选std::vector&lt;std::unique_ptr&lt;Node&gt;&gt; 而不是std::vector&lt;Node*&gt;,如果它被用作std::vector&lt;Node&gt; 的替代品就是这种情况。 std::vector&lt;Node&gt; 可能没问题,具体取决于 Node 对象的预期数量及其大小。
  • 如果有大量Nodes,它们必须存在于某个地方。指针必须指向某物。使用指向对象的指针向量而不是对象本身不会改变这一点。话虽如此,重新分配小指针向量与向量大对象相比,肯定会有所不同。但是您必须完全理解其含义,特别是在对象生命周期方面。否则,你最终会到处泄漏内存,而且会有很多好处。
  • 在 Ubuntu 20.04 上使用 g++ 9.3.0,“std::vector tVec;”占用 24 个字节,无论 sizeof(T) 和元素数量如何(即 tVec.size())。 [注意:一些向量实现不同。] 这意味着 tVec 的元素驻留在堆中,而 std::vector 负责指针和向量大小的增长。这意味着所使用的“大内存”(用于许多大 T 的)不在您系统的堆栈中。您对指针(或 smart_ptrs)的使用可能会浪费您的时间,并且操作起来会有些慢。

标签: c++ pointers templates struct


【解决方案1】:

如果我使用结构体向量,那么向量需要很大的内存来存储向量中的每个整个结构体。

无论您将它们存储在何处或如何存储,它们都会占用内存。节点必须在内存中的某个地方吗?实际上,指针向量总体上使用了更多内存,因为除了实际节点的内存之外,您还需要指针的内存。

指针向量有两个众所周知的性能缺陷:

  • 间接。访问元素的意思是:先访问vector中的指针,再访问取到的地址中的元素。
  • 缓存不友好:当您遍历节点向量时,所有节点都是相邻的并且一起被放入缓存中。当您有一个指针向量时,每个节点都可以位于内存中的任何位置。元素很少会在缓存中,并且会更快地从缓存中逐出。

这两者都很重要,在大多数情况下都会导致可衡量的性能损失。所以指针向量对性能几乎没有好处。

其他一些答案提到了搬迁。然而,这并不像最初看起来那么糟糕。首先,通过push_back 进行的重定位保证具有摊销常数复杂性。还有一些简单的方法可以进一步缓解它们,比如提前预订。如果重定位确实是一个问题——通过分析确定——那么更好的选择可能是std::list。

指针向量有一些有效用途,例如需要存储多态对象。如果您使用指针,请使用智能指针。

【讨论】:

    猜你喜欢
    • 2012-02-07
    • 2018-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多