std::vectorでイテレータループ内でのerase
std::vector<int> test; test.push_back(0); test.push_back(1); test.push_back(2); std::vector<int>::iterator i; for(i = test.begin(); i != test.end();) { if(*i == atoi(argv[1])) i = test.erase(i); else ++ i; }
で正常に動作する。
2007/04/22追記:eraseの戻り値がない場合
ダメな例:
std::vector<int>::iterator i; for(i = test.begin(); i != test.end(); ++ i) { if(*i == atoi(argv[1])) i = test.erase(i); }
や
std::vector<int>::iterator i; for(i = test.begin(); i != test.end(); ++ i) { if(*i == atoi(argv[1])) test.erase(i--); }
や
std::vector<int>::iterator i; for(i = test.begin(); i != test.end();) { if(*i == atoi(argv[1])) test.erase(i--); else ++ i; }
これだと最初の要素「0」を抜こうとするとSEGV。ちなみに「1」や「2」では下のコードは正常動作するからややこしー。
いままでC++5年以上ダメな例1or2で書いてて、今日はじめてSEGVに突き当たったよ。
2年前のコードは正しく書いてあった。orz
追記:
そもそも、std::removeやstd::remove_ifをvector::eraseと組み合わせて使えという話もあるけど、関数オブジェクトのみ受け付けるのでlambda式が自由にかけない今のC++だとちょっときついケースが多い。このぐらいシンプルな場合は素直にequal_toでOK。
boost::lambdaという手はあるけど、二回ループまわす代わりについでにやりたかったりする。
さらに追記:
http://ml.tietew.jp/cppll/cppll_novice/article/1428
で↑のコードが出ているのに誰も指摘していないのが気になる。私が間違っているのかなぁ。
突っ込み大歓迎