【问题标题】:Is std::vector good for frequent resizing?std::vector 是否适合频繁调整大小?
【发布时间】:2012-07-10 19:23:02
【问题描述】:

我正在创建一个我有小“粒子”的游戏。它们的数量变化非常频繁(每隔几秒钟),我想知道存储它们的最佳方式是什么。 std::vectorstd::deque 更适合这个吗?

是否可以保留永远不会被使用的空间(在那个容器中)(我有上限)?

【问题讨论】:

  • 给我们一些关于使用的更多信息。
  • 如果你只擦除一个向量的最后一项,它通常相当快。你能给出最大数量的粒子吗?
  • 使您的代码模块化,以便轻松更换容器类型和配置文件
  • 感谢您的建议!最大数量通常约为 100 - 150,因此我将使用向量并为其保留空间。

标签: c++ vector stl resize


【解决方案1】:

这真的取决于使用情况。如果您的向量未排序,如果您实际上是在移除该粒子,则在向量中找到它的复杂度为 O(n),并且整个向量将被复制,因此数据保持连续。使用双端队列,仍然需要 O(n) 才能找到,但删除是微不足道的。但是,如果你像这样迭代

foreach (particle in particles)
{
    if(particle.update() == END_OF_LIFE)
    {
        particle.alive = false;
    }
    else
    {
        particle.draw();
    }
}

你可以在没有显着开销的情况下做到这一点,但要插入新粒子,你需要遍历每个粒子以找到第一个可以替换的“死”粒子 (O(n)),或者跟踪该信息在单独的 std::list 中。

要有效回答,我们需要知道一件事 - 您是否需要对特定粒子进行索引(“给我列表中的第 1000 个粒子”)?另外,您是否曾经通过某个 ID 查找(“查找 id=421932 的粒子”)?如果是前者,vector 会在恒定时间内执行,而后者将由 std::unordered_set(c++ x11 版本的 hash_set,boost pre x11 中的类似选项)在恒定时间内执行,而 logn 时间由 std::set 执行。

【讨论】:

    【解决方案2】:

    如果顺序无关紧要,您可以将其替换为向量中的另一个粒子,而不是删除一个粒子(我认为它不重要)

    std::vector<Particle> particles;
    

    当您删除索引 i 处的粒子时 - 只需用最后一个填充空白空间:

    particles[i] = particles.back();
    particles.pop_back();
    

    如果使用指针向量,您可以使其更快。

    【讨论】:

    • 我很好奇:你为什么使用 resize(..) 而不是 pop_back()? pop_back() 有缺点吗?
    • @stefan:是的,pop_back 更好
    • @stefan 这还是很奇怪。为什么要使用赋值而不是swap
    • 我认为使用指针向量不会更快。使用指针向量,他将失去内存是连续的这一事实。这实际上取决于粒子实际上是什么以及将涉及哪种计算。
    • ... 在 C++11 中,您可以编写 particles[i] = std::move(particles.back()) 并获得两全其美的效果。当然,您的代码依赖于 C++11。
    【解决方案3】:

    如果你为vector预留了足够的空间,resize也不错,因为它不需要复制vector的内容。

    另一方面,由于避免了大规模的重新分配,因此出队可以比具有自动管理容量的向量更有效地增长,特别是在大序列中。

    【讨论】:

      猜你喜欢
      • 2010-11-12
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      相关资源
      最近更新 更多