【问题标题】:std::vector resize downwardstd::vector 向下调整大小
【发布时间】:2010-11-12 10:40:42
【问题描述】:

C++ 标准似乎没有说明两者对容量的副作用 resize(n)n < size()clear()

它确实声明了push_backpop_back 的摊销成本 - O(1)

我可以设想一种实现通常的容量变化 ala CLRS 算法(例如,放大时加倍,缩小时减半size to < capacity()/4)。 (Cormen Lieserson Rivest Stein)

谁有任何实施限制的参考?

【问题讨论】:

    标签: c++ vector resize std stdvector


    【解决方案1】:

    以较小的大小调用resize()vector 的容量没有影响。它不会释放内存。

    vector 释放内存的标准习惯用法是使用空的临时swap() swap()std::vector<T>().swap(vec);。如果要向下调整大小,则需要从原始向量复制到新的本地临时向量,然后将生成的向量与原始向量交换。

    更新:C++11为此添加了成员​​函数shrink_to_fit(),将capacity()减少为size()是一个非绑定请求。

    【讨论】:

    • 按照我的阅读方式,他询问的是对内存使用的影响——他特别询问了调整大小对容量的影响。该标准没有指定这种情况下的结果,但我能想到的唯一原因是希望释放未使用的内存。使用临时技巧进行交换是实现此目的的惯用方式。
    • 标准确实通过不为这些操作指定容量()的减少来指定结果。因此它不能减少。
    • 在某些环境中,在初始“构造”阶段之后禁止分配或释放内存。只要可以确定向量在操作期间不会尝试分配或释放内存,向量就可以在这种环境中使用。所以这个问题在这种情况下是相关的(把我带到这里)。
    • 使用 g++ 和 libstdc++ 10:std::vector::shrink_to_fit 进行新的分配。 myvector.data() 每次调用 shrink_to_fit() 时都会产生不同的地址
    【解决方案2】:

    实际上,标准确实规定了应该发生的情况:

    这是来自vector,但所有容器的主题都是相同的(listdeque 等...)

    23.2.4.2 向量容量[lib.vector.capacity]

    void resize(size_type sz, T c = T());

    6) 效果:

    if (sz > size())
        insert(end(), sz-size(), c);
    else if (sz < size())
        erase(begin()+sz, end());
    else
        ; //do nothing
    

    也就是说:如果指定给resize的大小小于元素个数,这些元素将从容器中删除。关于capacity(),这取决于erase() 对它做了什么。

    我无法在标准中找到它,但我很确定 clear() 被定义为:

    void clear()
    {
        erase(begin(), end());
    }
    

    因此,clear()capacity() 的影响也与erase() 对其的影响有关。按标准:

    23.2.4.3 矢量修饰符 [lib.vector.modifiers]

    iterator erase(iterator position);
    iterator erase(iterator first, iterator last);
    

    4) 复杂度:T的析构函数被调用的次数等于被擦除元素的次数......

    这意味着元素将被销毁,但内存将保持不变。 erase() 对容量没有影响,因此resize()clear() 也没有影响。

    【讨论】:

    • resize向下现在记录为等效于一系列pop_back()调用,而不是erase。这是否消除了容量不会改变的保证? (见stackoverflow.com/q/19941601/103167
    【解决方案3】:

    容量永远不会减少。我不确定标准是否明确说明了这一点,但这是暗示的:如果n &lt; capacity()resize(n) 不能使迭代器和对向量元素的引用无效。

    【讨论】:

      【解决方案4】:

      当我检查 gcc (mingw) 时,释放向量容量的唯一方法是 mattnewport 所说的。 将其与其他临时向量交换。 此代码适用于 gcc。

      template<typename C> void shrinkContainer(C &container) {
          if (container.size() != container.capacity()) {
              C tmp = container;
              swap(container, tmp);
          }
          //container.size() == container.capacity()
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-18
        • 1970-01-01
        • 2012-07-10
        • 1970-01-01
        • 1970-01-01
        • 2019-09-29
        • 1970-01-01
        • 2011-07-26
        相关资源
        最近更新 更多