【问题标题】:Can I reuse an invalidated iterator?我可以重用无效的迭代器吗?
【发布时间】:2014-07-11 00:34:08
【问题描述】:

以下代码有效(诚然,这不是执行此例程的最有效方法)。我的问题是,是否不鼓励像我在这里所做的那样重用迭代器?它会产生奇怪的行为吗?如果有,为什么?

std::map<char, int> map;

map['a'] = 10;
map['b'] = 30;
map['c'] = 50;
map['d'] = 70;


std::map<char, int>::iterator iterator = map.begin();

for (; iterator != map.end(); iterator++) {
    if (iterator->second == 30 || iterator->second == 50) {
        map.erase(iterator);
        iterator = map.begin();
    }
}

【问题讨论】:

  • 如果您的编译器支持 C++11,您可以使用 iterator = map.erase(iterator); 并避免多次遍历相同的元素。
  • 是的,没关系。 “无效”意味着您不能尝试使用其中存储的值;但你可以设置一个新值。

标签: c++ map iterator erase


【解决方案1】:

不,重新赋值给迭代器并重用它并没有错,因为赋值运算符运行后,旧值被完全覆盖。

    iterator = map.begin();

【讨论】:

    【解决方案2】:

    您没有使用无效的迭代器,但您的逻辑有缺陷。要修复它,请对您的代码进行一些小改动;如果您在当前迭代期间没有删除元素,则仅增加迭代器。使用您当前的代码,假设map 中的前两个元素满足擦除标准。然后第二个将不会被擦除,因为您在循环的第二次迭代中递增超过它。

    for (; iterator != map.end();) {
        if (iterator->second == 30 || iterator->second == 50) {
            map.erase(iterator);
            iterator = map.begin();
        } else {
            ++iterator;
        }
    }
    

    如果您的编译器支持 C++11,您可以这样做来擦除 map 中的元素

    for (; iterator != map.end(); ) {
        if (iterator->second == 30 || iterator->second == 50) {
            iterator = map.erase(iterator);
        } else {
            ++iterator;
        }
    }
    

    【讨论】:

    • 那么让我再确认一下。
    • @chris 这是一个有序容器,remove_if 将无法将元素移动到末尾。或者至少我一直这么认为。不能说我曾经尝试过自己做。
    • @Praetorian: remove_if 不会将元素移动到末尾。
    • @Blastfurnace 嗯?如果没有,那么 erase-remove idiom 将被称为 remove idiom。如果您的意思是将符合标准的元素与以下不符合标准的元素交换,那么是的,我同意。这并不是真正将元素移动到最后,但这就是我一直以来在概念上的想法。
    • @Praetorian:唯一移动的元素是那些不被删除的元素,它们向范围的开头移动。仍然需要擦除以删除最后未指定的值并设置物理大小以匹配新的逻辑大小。
    猜你喜欢
    • 2011-03-26
    • 1970-01-01
    • 2018-03-06
    • 2011-03-17
    • 2013-12-08
    • 1970-01-01
    • 2011-12-22
    • 2016-07-24
    相关资源
    最近更新 更多