【问题标题】:Iteratively insert into std::list and then convert to std::vector for random access?迭代插入 std::list 然后转换为 std::vector 以进行随机访问?
【发布时间】: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::vectorstd::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

标签: c++ list vector


【解决方案1】:

在这种情况下,我使用 std::list 会更有效吗

可能不会。这通常比直接推送到向量更昂贵。

或者转换的成本是否会超过收益?

一般来说,列表的高成本主要是问题所在。


要查明这些合理的假设是否真的正确,您应该对其进行衡量。如果您测量一个明显更快,那么这可能是更有效的选择。

额外提示:不要 push_back,而是 emplace_back。根据班级的不同,这可能会更快一些。

以下是我建议衡量的替代方案:

  • 只是一个简单的向量和安放。
  • 填充向量后使用*some number*shrink_to_fit 保留向量。
  • 也许可以改用双端队列。

【讨论】:

    猜你喜欢
    • 2012-05-07
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多