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