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
相关文章读者评论发表评论 |