我们有时候想要删除容器中的多个元素。普通做法可能是逐个进行删除。但这要做的话效率比较低。其实std中的list、set和map容器是有办法边遍历边删除的。使用这种方法,优点很明显,高效省事。缺点就是这种用法并没有出现在标准库的文档中。虽然经测试,windows
vs2005
vs2008,gcc4.1下都可以pass。但日后编译器升级了就不一定了。但我觉得这个hack应该会保留下去,因为太方便了。
for
(list<int>::iterator it = lt.begin();
it != lt.end(); ++ j)
{
ASSERT_EQ(*it, j);
if (j ==
to_delete)
{
lt.erase(it++);//
注意,这句话很关键,不能分成两句:lt.erase(it);
it++;,否则斯巴达,怎么样非常hack吧哈哈
}
else
{
++ it;
}
}
下面是测试这种方法是否可用的自动化测试代码,想用这种方法前现在自己的编译器上编译运行下。如果pass了再用。(注意,其实pass也不一定就ok,因为只测试了1w次,这个可以自己调下)
==========================自动化测试代码的分割线===============================
#include <iostream>
#include <list>
#include <set>
#include <map>
#include <cstdlib>
using namespace std;
#define ASSERT_EQ(X, Y) if(X != Y) {cout
<< X <<
" != " << Y
<< endl;exit(1);}
int main()
{
for (int
times = 0; times < 10000; times ++)
{
int
element_cnt = (rand() % 1000) + 1;
int
to_delete = rand() % element_cnt;
list<int> lt;
for (int i =
0; i < element_cnt; ++ i)
{
lt.push_back(i);
}
int j =
0;
for
(list<int>::iterator it = lt.begin();
it != lt.end(); ++ j)
{
ASSERT_EQ(*it, j);
if (j ==
to_delete)
{
lt.erase(it++);
}
else
{
++ it;
}
}
j = 0;
for
(list<int>::iterator it = lt.begin();
it != lt.end(); ++ j, ++ it)
{
if (j
< to_delete)
{
ASSERT_EQ(j,
*it);
}
else
{
ASSERT_EQ(j+1, *it);
}
}
}
cout
<< "pass test"
<< endl;
for (int
times = 0; times < 10000; times ++)
{
int
element_cnt = (rand() % 1000) + 1;
int
to_delete = rand() % element_cnt;
set<int> st;
for (int i =
0; i < element_cnt; ++ i)
{
st.insert(i);
}
int j =
0;
for
(set<int>::iterator it = st.begin();
it != st.end(); ++ j)
{
ASSERT_EQ(*it, j);
if (j ==
to_delete)
{
st.erase(it++);
}
else
{
++ it;
}
}
j = 0;
for
(set<int>::iterator it = st.begin();
it != st.end(); ++ j, ++ it)
{
if (j
< to_delete)
{
ASSERT_EQ(j,
*it);
}
else
{
ASSERT_EQ(j+1, *it);
}
}
}
cout
<< "pass test"
<< endl;
for (int
times = 0; times < 10000; times ++)
{
int
element_cnt = (rand() % 1000) + 1;
int
to_delete = rand() % element_cnt;
map<int, int> mp;
for (int i =
0; i < element_cnt; ++ i)
{
mp[i] =
i;
}
int j =
0;
for
(map<int, int>::iterator it =
mp.begin(); it != mp.end(); ++ j)
{
ASSERT_EQ(it->first, j);
if (j ==
to_delete)
{
mp.erase(it++);
}
else
{
++ it;
}
}
j = 0;
for
(map<int, int>::iterator it =
mp.begin(); it != mp.end(); ++ j, ++ it)
{
if (j
< to_delete)
{
ASSERT_EQ(j,
it->first);
}
else
{
ASSERT_EQ(j+1, it->first);
}
}
}
cout
<< "pass test"
<< endl;
return
0;
}