删除元素

删除最后一个元素:

std::vector<int> v{ 1, 2, 3 };
v.pop_back();                           // v becomes {1, 2}

删除所有元素:

std::vector<int> v{ 1, 2, 3 };
v.clear();                              // v becomes an empty vector

按索引删除元素:

std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
v.erase(v.begin() + 3);                 // v becomes {1, 2, 3, 5, 6}

注意: 对于 vector 删除不是最后一个元素的元素,必须复制或移动删除元素之外的所有元素以填补空白。

删除范围中的所有元素:

std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
v.erase(v.begin() + 1, v.begin() + 5);  // v becomes {1, 6}

注意: 上述方法不会改变向量的容量,只会改变大小。请参见矢量大小和容量

删除一系列元素的 erase 方法通常用作擦除 - 移除 习语的一部分。也就是说,首先 std::remove 将一些元素移动到向量的末尾,然后 erase 将它们关闭。对于小于向量的最后一个索引的任何索引,这是相对低效的操作,因为必须将擦除段之后的所有元素重新定位到新位置。对于需要有效删除容器中任意元素的速度关键应用程序,请参阅 std::list

按值删除元素:

std::vector<int> v{ 1, 1, 2, 2, 3, 3 };
int value_to_remove = 2;
v.erase(std::remove(v.begin(), v.end(), value_to_remove), v.end()); // v becomes {1, 1, 3, 3}

按条件删除元素:

// std::remove_if needs a function, that takes a vector element as argument and returns true, 
// if the element shall be removed
bool _predicate(const int& element) {
    return (element > 3); // This will cause all elements to be deleted that are larger than 3
}
...
std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
v.erase(std::remove_if(v.begin(), v.end(), _predicate), v.end()); // v becomes {1, 2, 3}

通过 lambda 删除元素,而不创建其他谓词函数

Version => C++ 11
std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
v.erase(std::remove_if(v.begin(), v.end(),
     [](auto& element){return element > 3;} ), v.end()
);

从循环中按条件删除元素:

std::vector<int> v{ 1, 2, 3, 4, 5, 6 };
std::vector<int>::iterator it = v.begin();
while (it != v.end()) {
    if (condition)
        it = v.erase(it); // after erasing, 'it' will be set to the next element in v
    else
        ++it;             // manually set 'it' to the next element in v
}

虽然重要的是不要在删除时增加 it,但是在循环中重复擦除时应考虑使用不同的方法。考虑 remove_if 以获得更有效的方式。

从反向循环中按条件删除元素:

std::vector<int> v{ -1, 0, 1, 2, 3, 4, 5, 6 };
typedef std::vector<int>::reverse_iterator rev_itr;
rev_itr it = v.rbegin();

while (it != v.rend()) { // after the loop only '0' will be in v
    int value = *it;
    if (value) {
        ++it;
        // See explanation below for the following line.
        it = rev_itr(v.erase(it.base()));
    } else
        ++it;
}

请注意前一个循环的一些要点:

  • 给定一个指向某个元素的反向迭代器 it,方法 base 给出了指向同一元素的常规(非反向)迭代器。

  • vector::erase(iterator) 擦除迭代器指向的元素,并将迭代器返回给定元素后面的元素。

  • reverse_iterator::reverse_iterator(iterator) 从迭代器构造一个反向迭代器。

总而言之,线 it = rev_itr(v.erase(it.base())) 说:取反向迭代器 it,让 v 擦除其常规迭代器指向的元素; 获取生成的迭代器,从中构造一个反向迭代器,并将其分配给反向迭代器 it

使用 v.clear() 删除所有元素不会释放内存( 向量的 capacity() 保持不变)。要回收空间,请使用:

std::vector<int>().swap(v);
Version => C++ 11

shrink_to_fit() 释放未使用的矢量容量:

v.shrink_to_fit();

shrink_to_fit 并不能保证真正回收空间,但大多数现有的实施都可以。