删除元素
删除最后一个元素:
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
并不能保证真正回收空间,但大多数现有的实施都可以。