【问题标题】:How to remove element(s) from std::vector without resizing it如何在不调整大小的情况下从 std::vector 中删除元素
【发布时间】:2011-07-26 16:25:37
【问题描述】:

迭代器擦除(迭代器位置);

迭代器擦除(迭代器优先, 迭代器最后);

擦除元素从向量中移除 容器或者单个元素 (位置)或一系列元素 ([第一,最后))。

这有效地减少了向量 元素数量的大小 删除,调用每个元素的 之前的析构函数。

和:

删除

删除所有等于 范围内的给定值, 由 [first, last) 定义。删除是 通过移动中的元素来完成 范围以这样的方式,需要 元素被覆盖。要素 在新旧两端之间 范围保持不变。迭代器 返回范围的新结尾。

有没有办法在不调整向量大小的情况下从迭代器范围内的 std::vector 中删除元素(类似于删除,但从 [first, last] 中删除所有元素)?我需要保持它在运行时达到的最大大小以防止重新分配。

谢谢!

【问题讨论】:

    标签: c++ stl


    【解决方案1】:

    resize 永远不会减少向量的capacity - 您可以安全地使用erase

    使用reserve 使向量为一定数量的项目预分配空间。除非您实际上超过了这个限制,否则inserteraseresize 不会导致重新分配。如果超过它,向量将在内部reserve 更多空间 - 但它不会减少内部容量。

    【讨论】:

    • 我不知道尺寸。我想让向量在运行时调整它的大小。
    • @Felics:向量永远不会减少容量(除非你swap) - 无论你如何擦除元素,你在运行时达到的容量都不会下降。向量的sizecapacity 不一样。
    • @Felics:一个向量只有在它变得太大时才会重新分配,或者什么时候明确告诉它变小。 size 为您提供向量中实际元素的数量,而capacity 为您提供向量在不重新分配的情况下可以容纳的元素数量。
    • @Erik 我知道大小和容量不一样,但我在某处读到擦除会降低它的容量。如果它不会减少它的容量,我将使用擦除
    • @Space_COwbOy:我发现您的评论可能会被误解。如果您在提供较小尺寸的向量上调用 resize(),您是在告诉它更小,但该向量将不会减少容量。向量中没有允许您减少容量的操作,实现它的唯一方法是通过 交换 与向量的较小副本,但我不会称之为 告诉向量变小.
    【解决方案2】:

    我想你可能误解了向量的容量和它的大小之间的区别。

    容量是底层数组的实际大小。大小是该数组中实际使用的元素数。

    当您调用擦除/删除时,您正在从数组中删除元素并将项目向前移动。但是,大阵列不会改变它的容量。只有向量的大小字段发生了变化(可能只是一个 size_t),以及一些元素被移动了。

    一个简单的例子: 这是一个容量为 10,大小为 4 的 int 向量。

    | 1 | 2 | 4 | 8 | Garbage | Garbage | Garbage | Garbage | Garbage | Garbage |

    现在,假设我们要删除索引 1 处的项目。

    操作类似于这样:

    1. 销毁索引 1 处的项目(在本例中为整数 2)

    2. 将索引 1 之后有效的所有元素向前移动,但是需要很多位置来确保数组的开头和最后一个有效项之间没有垃圾(在这种情况下,将所有元素向前移动 1)。

    3. 将 size 字段减小为删除了多少项目(在本例中为 1)。

    最终向量: | 1 | 4 | 8 | Garbage | Garbage | Garbage | Garbage | Garbage | Garbage | Garbage |

    没有必要重新分配任何数组,因为向量的容量没有改变。

    我不完全确定前移操作的语义,在前移项目时可能会调用复制构造函数/赋值运算符重载(如果有的话)。

    【讨论】:

    • 你说最终向量是1 | 4 | 8 |垃圾 |垃圾 | ... |但第一个垃圾实际上是 8。
    • @Ogen 我认为假设第一个垃圾具有任何价值是未定义的行为。它可能在每个当前实现中都有一个值 8,但我当然不会依赖这个。
    【解决方案3】:

    我认为您想使用reserve 函数在向量中为所需数量的项目保留空间。

    看看这里:http://www.cplusplus.com/reference/stl/vector/reserve/

    在从向量中删除项目之前,您可以使用当前大小调用 reserve 以保持容量不变。

    请求更改容量

    请求的容量 分配的存储空间 矢量容器的元素位于 至少足以容纳 n 个元素。

    这会通知向量 尺寸增加,尽管注意到 参数 n 告知最小值, 所以产生的容量可能是任何 容量等于或大于此。

    当n大于当前 容量,尝试重新分配 在调用此函数期间。如果 成功,它允许没有进一步 将发生自动重新分配 因为调用了 vector::insert 或 vector::push_back 直到向量 大小至少超过 n (这 保留迭代器的有效性 所有这些未来的电话)。

    重新分配会使所有 先前获得的迭代器, 元素的引用和指针 向量。

    无论如何,调用这个函数 从不影响包含的元素 在向量中,也不是向量大小 (为此,请参阅 vector::resize 或vector::erase,它修改 矢量大小和内容)。

    【讨论】:

    • 是的,但是当我调用erase时,它会重新分配。
    • 真的吗?为什么?我原以为它只会在想要减少容量时重新分配。如果您指定了保留大小,那么它不会减少容量,因此不会重新分配。
    • @Felics:不,不会。您需要区分size(容器中的元素数量)和capacity(在不分配更多内存的情况下可以包含的元素数量)。事实上,vector 的容量永远不会缩小(所以我们需要使用tricks 使其适合大小),所以你的问题不存在。
    • @Luc Touraille 我不知道向量在使用擦除时从不调整其容量。感谢您的信息。
    【解决方案4】:
    iterator erase ( iterator first, iterator last );
    

    这就是你想要做的。调用元素的析构函数这一事实与向量的最大大小(即容量)无关,通常不会减少。当您从向量中删除一个元素时,向量的大小(= 包含的元素的数量)会减小,但在大多数情况下容量不会改变。

    【讨论】:

      【解决方案5】:

      std::vector 在减小它的大小时不会减小它的容量。实际上,要缩小向量的容量,您需要使用 swap-with-empty-vector 习惯用法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        相关资源
        最近更新 更多