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
で↑のコードが出ているのに誰も指摘していないのが気になる。私が間違っているのかなぁ。

突っ込み大歓迎