我有一个这样的对象:
class Node {
float x, y, z;
size_t tag;
bool isFree;
std::vector<size_t> connections; // Usually ~10-100 in length
};
只是为了让您了解尺寸。这些节点对象的列表包含数百万个实例,我将其称为std::vector<Node> masterNodes
。我在其他地方有一个函数返回这些对象的容器,例如:
std::vector<Node> find_nodes()
{
std::vector<Node> nodes;
// copy some elements from masterNodes that meet our conditions
return nodes;
}
我的问题是返回Node *的向量会更高效,或者我的编译器是否会对此进行优化以使得像我这样的对象的增益最小化? E.g。
std::vector<Node*> find_nodes()
{
std::vector<Node*> nodes;
// point to some elements from masterNodes that meet our conditions
return nodes;
}
我已经看到一些回复(例如this one)建议副本可能几乎与返回指针一样有效,并承认返回指向向量元素的指针的危险。
答案 0 :(得分:1)
返回Node*
的向量会更有效率,因为nodes
是来自{{1}的Node
的副本的向量你的masterNodes
比指针大得多。没有像返回值优化或移动语义这样的东西可以帮助您拥有(并返回)复制向量这一事实。
顺便说一句,您可以返回Node
而不是vector<vector<Node>::iterator>
。它与vector<Node*>
一样有效,至少在发布版本中,但通常在调试版本中有一些集成检查,这可能有所帮助。
答案 1 :(得分:1)
现实生活中的表现在很大程度上取决于硬件,如果您知道如何使用它,可以获得很多。
使用参考位置时,可以获得最大的硬件引起的性能提升之一。这意味着在时间和空间上处理非常接近的数据可以更好地利用内置CPU缓存,这比使用主存储器(RAM)快得多。
这就是为什么复制数据以允许连续的本地访问可以提高性能。
与此相反的是使用间接。间接是使用引用或指针而不是值本身访问内存的能力。这样可以避免复制内容,但是当硬件必须始终从主内存中的不同位置获取每一位数据时,不可以充分利用CPU缓存。
基本上,复制大件事会导致一次性的性能损失,但是如果你将使用数据做很多工作,你可以使用参考地点来弥补这一点。
但是,您必须自己测试才能知道什么最适合您。在你的情况下,复制数据的成本可能会比更好地利用CPU缓存所带来更大的性能损失。
答案 2 :(得分:0)
当您使用std::vector<Node>
作为方法返回时,您复制所有数据并且需要时间。
使用std::vector<Node*>
允许您只拥有数据地址,并且不会进行重复。但是,如果您使用此选项,则必须小心修改数据,因为修改是在 masterNodes 中完成的。
答案 3 :(得分:0)
根据参考资料,你应该尝试std::copy_if算法:
实际上,如果值类型为std::memmove,std :: copy的实现将避免多个赋值并使用批量复制函数,例如TriviallyCopyable。
您可以使Node
实现符合要求 TriviallyCopyable (使用std :: array,而不是std :: vector进行连接),因此使用std::copy_if
应该非常快。
另一方面,复制节点受内存限制,如果内存不足,可能会出现内存不足错误,如果您确定永远不会返回超过100个节点,好吧,你有这个控制。
如果使用指针,应用程序必须管理内存,这会减少使用的内存量,但可以增加内存管理所需的时间。
但是你得到的最佳答案是你的两种选择。