【发布时间】:2021-05-22 23:43:31
【问题描述】:
假设我有一种情况,我正在迭代地填充向量/列表,但我不知道事先会有多少元素。例如,代码可能看起来或多或少是这样的:
std::vector<MyClass> mythings;
for(int i = 0; i < *some number*; ++i){
if(*some condition here*){
mythings.push_back(MyClass());
}
}
我知道push_back 用于std::vector 时效率不高。因此,在上面的代码块中,我可以将mythings 更改为std::list,并且可能会更快,因为std::list 是作为链表实现的。但是,假设我知道我需要对刚刚创建的列表/向量进行随机访问。对于随机访问,std::vector 会快得多。所以在这种情况下使用std::vector 和std::list 都有自己的缺点。
在这种情况下,我在创建列表/向量时使用std::list,然后将其转换为std::vector 会更有效吗(例如,在这个问题中:One liner to convert from list<T> to vector<T>)这样我就可以利用std::vector 的随机访问?或者转换的成本是否会超过收益?
【问题讨论】:
-
如果已知
*some number*,使用std::vector并通过reserve()进行预分配可能会更好。 -
做一些实验怎么样?
-
为什么
push_back效率不高?分析后,这段代码真的是你程序的瓶颈吗?如果没有,您可能会过早地尝试对其进行优化。* some number *在这里谈论的大约有多少个元素? -
视情况而定。可能要尝试的方法是预先分配向量,使用
emplace_back而不是push_back和/或使用std::move添加到mythings,使用std::deque,或迭代一次以计算将要使用的事物的数量添加,预分配,然后通过迭代添加它们。 -
@dfriend21 我假设
push_back强制非预分配向量最多进行 log(n) 重新分配调用。 20 次重新分配真的会严重破坏您的应用程序的性能吗?推荐阅读:Eric Lippert: performance rant