在这种情况下,问题场景是一个游戏,因此所有资源都在开始时分配,然后迭代一个级别。
存储在 vector 中的对象是复杂类的实例,当然,在加载时将它们实际复制到 vector 中很耗时,但关注度较低。
但如果我主要关心的是运行时类对象的迭代速度,我是否最好将类对象本身存储在 vector 中,而不是像传统推荐的那样只存储指向类对象的指针?
在这个例子中我不担心内存管理,只担心迭代速度。
最佳答案
我迟到了才回答这个问题,但性能方面很重要,到目前为止在线答案都是纯理论的和/或只关注内存管理方面。所以这是我最近尝试过的三个相关场景的一些实际基准测试信息。您的结果可能会有所不同,但至少可以了解实际应用中的结果。
类(class)A
此处引用的成员字段大约有 10 个,其中一半是原语,另一半是 std::string
, std::vector<int>
, 和其他动态大小的容器。该应用程序已经相当优化,因此我们想看看现在哪种体系结构可以为我们提供最快的 A
集合循环。 . A
中任一项的值对象的成员字段可能会在应用程序生命周期内发生变化,但 A
的数量 vector 中的对象不会在我们执行的许多重复迭代中发生变化(这种连续迭代约占该应用程序执行时间的 95%)。在所有情况下,循环都是使用典型的 std::iterator
执行的。或 std::const_iterator
.每个枚举A
对象至少访问了几个成员字段。
场景 1 — 对象指针 vector
虽然最简单,std::vector<A*>
的这个架构结束时比其他人稍慢。
场景 2 — 对象指针 vector ,使用 Placement New 分配对象
这种方法背后的想法是,我们可以通过强制将对象分配到连续的内存空间来改善缓存的局部性。所以 std::vector<A*>
std::vector
保证对象指针的连续性实现和 A
对象本身在堆上也是连续的,因为我们使用了 placement new 习语。我使用了此 answer 中概述的相同方法;可以找到有关新安置的更多信息 here .
此场景比场景 1 快 2.7%。
场景 3 — 对象 vector
这里我们使用std::vector<A>
直接地。 std::vector
实现保证了我们的 A
对象在内存中是连续的。请注意 std::vector
对象确实涉及对 A
的移动和复制构造函数的考虑.为避免不必要的移动和/或重建,最好std::vector.reserve()
预先(如果可能的话)可能需要的最大尺寸,然后使用 std::vector.emplace_back()
(而不是 push_back()
)如果可能的话。循环遍历此结构是最快的,因为我们能够消除一级指针间接寻址。
此方法比方案 1 快 6.4%。
一个相关answer另一个问题也表明普通对象(作为类成员)可以比各自的指针(作为类成员)快得多。
关于C++ - 指向对象的指针 vector 的性能与对象的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22703663/