繁体   English   中英

递增迭代器,用作std :: multimap擦除范围的第一个和最后一个

[英]Incrementing iterator that is used as first and last of std::multimap erase range

在运行一个显示如何从std :: map / multimap删除范围的示例时,我注意到以下代码中的异常行为:

#include <map>
#include <iostream>
#include <string>

int main()
{
    std::multimap<int, std::string> myMap;

    myMap.insert(std::make_pair(3, "three1"));
    myMap.insert(std::make_pair(3, "three2"));
    myMap.insert(std::make_pair(3, "three3"));
    myMap.insert(std::make_pair(45, "fourty five"));
    myMap.insert(std::make_pair(-1, "minus one"));

    std::multimap<int, std::string>::iterator iter = myMap.find(3);
    if (iter != myMap.end()) {
        myMap.erase(iter, iter++); //segmentation fault(!)
    }

    for (auto element : myMap) {
        std::cout << element.first << " -> " << element.second << std::endl;
    }
    return 0;
}

我使用命令g++ --std=c++11 main.cpp构建(我使用g ++ 5.2.1)。

为什么迭代器的增量递增会导致分段错误? 我宁愿说这应该创建此迭代器的2个副本,将它们传递到擦除方法中,“不删除任何内容”,就像编码myMap.erase(iter, iter); 然后增加iter

该段错误背后的逻辑是什么?

这是对iter迭代器的无效使用吗? 如果是这样-为什么?

BTW。 当我使用预增量myMap.erase(iter, ++iter)时,它会编译myMap.erase(iter, ++iter)并且在这里它像上面提到的那样“不擦除”。

未定义对函数调用的参数求值的顺序。 所以当你写:

   myMap.erase(iter, iter++); //segmentation fault(!)

编译器可以自由选择是否先评估第二个参数。 当您使用相同的迭代器但有副作用时,您会得到未定义的行为( 请参阅C ++标准的1.9 / 15部分 )。

例如,如果编译器首先评估第二个参数iter++ ,则递增的迭代器将用作第一个参数,而第二个参数不递增iter 结果是:传递给擦除()的范围将是[std::next(iter), iter) -该函数可能会尝试擦除超出范围的元素(即UB)。

正如David在评论中建议的那样,您可以使用iter = myMap.erase(iter) (或使用无副作用的范围iter = myMap.erase(iter)解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM