专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »C 教程 » iterator方法:erase思路方法是否影响其它iterator? »正文

iterator方法:erase思路方法是否影响其它iterator?

来源: 发布时间:星期日, 2009年8月16日 浏览:6次 评论:0
有时候会有这么种不太常见需求:从个map中删除所有符合某种条件项目而这种条件和mapkey基本没啥关系

比如个存储学生花名册mapkey为学号()value为姓名()如果要按学号删除很容易但如果需要删除该map中所有姓“张”学生就只能遍历它比较了

using std;
typedef map<, > MAP;
bool canDrop(const MAP::value_type & v) {
0 strncmp(v.second.c_str, "张", 2);
}
using std;
typedef map<, > MAP;
bool canDrop(const MAP::value_type & v) {
0 strncmp(v.second.c_str, "张", 2);
}

下面是显而易见思路方法 :

// 第种思路方法(思路方法)!!
for (MAP::iterator it = theMap.begin; theMap.end!=it; it) {
(canDrop(*it)) {
// :当erase执行以后it立刻就失效了在执行到for循环it时就会出现未知后果
theMap.erase(it);
}
}
// 第种思路方法(思路方法)!!
for (MAP::iterator it = theMap.begin; theMap.end!=it; it) {
(canDrop(*it)) {
// :当erase执行以后it立刻就失效了在执行到for循环it时就会出现未知后果
theMap.erase(it);
}
}

如果用是VC编译器由于它对erase思路方法扩展所以用下面思路方法可以正确完成需求:

// 第2种思路方法仅适用于VC
for (MAP::iterator it = theMap.begin; theMap.end!=it;) {
(canDrop(*it)) {
// VC扩展了erase思路方法使它返回下个合法迭代器
it = theMap.erase(it);
} {
it;
}
}
// 第2种思路方法仅适用于VC
for (MAP::iterator it = theMap.begin; theMap.end!=it;) {
(canDrop(*it)) {
// VC扩展了erase思路方法使它返回下个合法迭代器
it = theMap.erase(it);
} {
it;
}
}

可惜C标准中map::erase思路方法并不返回任何值所以上述代码在g等编译器中无法通过编译为了符合标准下面有种安全思路方法——即将不需要删除项Copy到另个新容器里然后交换两个容器内容

// 第3种思路方法适用任何编译器但有额外开销
MAP tmp; // 临时容器
for (MAP::iterator it = theMap.begin; theMap.end!=it; it) {
(!canDrop(*it)) {
// 复制不需要删除荐到临时容器
tmp.insert(*it);
}
}
theMap.swap(tmp); // 交换两个容器内部此时 theMap 中包含正确
// 第3种思路方法适用任何编译器但有额外开销
MAP tmp; // 临时容器
for (MAP::iterator it = theMap.begin; theMap.end!=it; it) {
(!canDrop(*it)) {
// 复制不需要删除荐到临时容器
tmp.insert(*it);
}
}
theMap.swap(tmp); // 交换两个容器内部此时 theMap 中包含正确

这种“复制不需要删除项到临时容器”思路方法符合C标准也很容易理解但如果不需要删除项目数很多时(或者MAP值拷贝开销很大时)就不太适合了下面是另种思路方法:

// 第4种思路方法
for (MAP::iterator it = theMap.begin; theMap.end!=it;) {
(canDrop(*it)) {
// 在erase的前先递增迭代器此时由于erase尚未被所以递增后迭代器有效
// 然后用迭代器原始值来erase确何删除正确
theMap.erase(it);
} {
it;
}
}
// 第4种思路方法
for (MAP::iterator it = theMap.begin; theMap.end!=it;) {
(canDrop(*it)) {
// 在erase的前先递增迭代器此时由于erase尚未被所以递增后迭代器有效
// 然后用迭代器原始值来erase确何删除正确
theMap.erase(it);
} {
it;
}
}

上例中it这个操作首先保存了it原始值然后对it进行自增操作由于此时erase尚未被所以it原始值有效自增后it也是有效;然后将it原始值传递给erase思路方法正确地删掉项目

现在问题是maperase操作除了影响被删除项目iterator(使指向这个项目iterator变成无效)还会影响其它iterator吗?比如说下面这种思路方法来完成需求:

// 第5种思路方法
vector<MAP::iterator> itList;
// 保存所有要删除项目iterator到临时容器
for (MAP::iterator it=theMap.begin; theMap.end != it; it) {
(canDrop(*it)) {
itList.push_back(it);
}
}
// 遍历临时容器取出里面iterator删除
for (vector<MAP::iterator>::iterator it2 = itList.begin; itList.end != it2; it2) {
theMap.erase( *it2 );
}
// 第5种思路方法
vector<MAP::iterator> itList;
// 保存所有要删除项目iterator到临时容器
for (MAP::iterator it=theMap.begin; theMap.end != it; it) {
(canDrop(*it)) {
itList.push_back(it);
}
}
// 遍历临时容器取出里面iterator删除
for (vector<MAP::iterator>::iterator it2 = itList.begin; itList.end != it2; it2) {
theMap.erase( *it2 );
}

从测试结果来看那些保存在临时容器里iterator并不其它iterator失效而失效

不过这是C标准吗?如果标准确规定了erase并不影响其它iterator那么第 4种思路方法显然是最好……可惜我查了半天没查到有知道达人不妨告诉我谢谢
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: