C++ STL 容器删除元素最佳实践
经常写 C++ 的同学,少不了和 STL 容器打交道。慎重选择删除元素的方法,至关重要,因为稍微不注意,就会踩坑。
不多 BB,来看代码。
bool badValue(int) { return true; } // 返回x是否为"坏值"
int test_item_9()
// 第一种情况:删除 c 中所有值指定值 2021 的元素
std::vector<int> c1;
c1.erase(std::remove(c1.begin(), c1.end(), 2021), c1.end()); // 当c1是vector, string或deque时,erase-remove习惯用法是删除特定值的元素的最好办法
std::list<int> c2;
c2.remove(2021); // 当c2是list时,remove成员函数是删除特定值的元素的最好办法
std::set<int> c3;
c3.erase(2021); // 当c3是标准关联容器时,erase成员函数是删除特定值元素的最好办法
// 第二种情况:删除判别式(predicate)返回 true 的每一个对象
c1.erase(std::remove_if(c1.begin(), c1.end(), badValue), c1.end()); // 当c1是vector, string或deque时,这是删除使badValue返回true的对象的最好办法
c2.remove_if(badValue); // 当c2是list时,这是删除使badValue返回true的对象的最好办法
for (std::set<int>::iterator i = c3.begin(); i != c3.end();) {
if (badValue(*i)) c3.erase(i++); // 对坏值,把当前的i传给erase,递增i是副作用
else ++i; // 对好值,则简单的递增i
}//当对关联式容器来说
// 第三种情况,每次元素被删除时,还需要都向一个日志(log)文件中写一条信息
std::ofstream logFile;
for (std::set<int>::iterator i = c3.begin(); i != c3.end();) {
if (badValue(*i)) {
logFile << "Erasing " << *i << '\n'; // 写日志文件
c3.erase(i++); // 对坏值,把当前的i传给erase,递增i是副作用
else ++i; // 对好值,则简单第递增i
}//当对关联式容器来说
for (std::vector<int>::iterator i = c1.begin(); i != c1.end();) {
if (badValue(*i)) {
logFile << "Erasing " << *i << '\n';
i = c1.erase(i); // 把erase的返回值赋给i,使i的值保持有效