【问题标题】:std::vector resize(0) or clear() - but keep it's capacitystd::vector resize(0) 或 clear() - 但保持它的容量
【发布时间】:2017-03-16 17:40:59
【问题描述】:

我正在将许多对象合并到一个包含渲染数据(网格)的向量中。这个向量在每一帧上都会被清除和重新填充(嗯,几乎)。

问题是在我的情况下,清除然后再次保留向量大小会对性能产生巨大影响,因为clear() 也可能会改变容量。

换句话说,我需要控制向量的容量何时发生变化。我想保留旧容量相当长的一段时间,直到我自己决定是时候改变它了。

我看到两个选项:

  • 弄清楚如何控制std::vector 的容量何时发生变化
  • 为大型内存对象实现一个内存池,它将获取

更新

此外,如果调用了 resize(10),后来又调用了 resize(5)(只是为了说明,将实际数字乘以几百万)怎么办?

稍后对resize(5) 的调用是否会导致向量重新分配?

【问题讨论】:

  • 为什么你认为.resize(0) 会改变容量? std::vector::resize[...]Vector capacity is never reduced when resizing to smaller size because that would invalidate all iterators, rather than only the ones that would be invalidated by the equivalent sequence of pop_back() calls.[...]std::vector::clear也一样
  • vector resizeclear 绝不允许减少容量。这样做的唯一方法是swapshrink_to_fit
  • @NathanOliver From std::vector::clear : "保持vector的容量()不变(注意:标准对容量变化的限制在vector::reserve的规范中,见[1])" Note 1
  • @Benjist 下次使用 cppreference。
  • @benjist cplusplus.com 是一个糟糕的网站,有很多错误

标签: c++ c++11 vector


【解决方案1】:

实际上clear成员函数保持向量容量不变。它只销毁(调用析构函数)每个向量元素并将向量大小设置为 0。

在这种情况下,每次迭代,我都会调用clear()来销毁所有向量元素,然后调用成员函数reserve(size),在向量容量太小的情况下,将其增加到至少size

【讨论】:

    【解决方案2】:

    这个向量在每一帧都会被清除和重新填充(嗯,几乎)。

    我会推荐一种不同的方法。

    创建一个作为渲染数据缓冲区的类。

    如果我没记错的话,你永远不会减少缓冲区的容量。您仅在需要时增加其容量。

    确保类是一个实现细节,并且只构造实例。

    这是我所想的框架实现。

    namespace Impl_Detail
    {
       struct Buffer
       {
          size_t capacity;
          size_t size;
          std::vector<char> data;
    
          // Pick whatever default capacity makes sense for your need.
          Buffer(size_t cap = 100) : capacity_(cap), size_(0), data(cap) {}
    
          void ensureCapacity(size_t cap)
          {
             if ( capacity_ < cap )
             {
                capacity_ = cap;
                data.resize(capacity_);
             }
          }
    
    
          // Add any other helpful member functions as needed.
       };
    
       // Create an instance and use it in the implementation.
       Buffer theBuffer;
    }
    

    【讨论】:

    • 另外,使用这种方法,创建一个变量“int amountUsed”,而不是“清除”数组,您只需将“amountUsed”设置为零,并根据需要覆盖现有值。只需覆盖数据并忽略“amountUsed”索引之后的所有内容。
    • @JasonLang,size 的目的是为这个角色服务。
    • 这一切似乎有点不必要。为什么不直接使用 std::vector::reserve()?
    • 因为你无法自己控制内存。我们使用的一个有用的性能附加是使该测试预期为假。那就是if (unlikely(capacity_ &lt; cap))。然后,一个专门的竞技场分配器会调用确保大小的东西,但它通常会以指数增长来完成,而不仅仅是将大小调整到给定的容量。此外,此时,您也可以控制内存的位置,而不仅仅是让 std::vector 在堆上分配。
    猜你喜欢
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 2021-03-26
    相关资源
    最近更新 更多