[英]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.