プログラミング、ゲームシステムなど普段考えたことについてのメモ帳代わり。
No.9
2010/01/29 (Fri) 07:32:12
卒論のプログラム作成中、エラーが起き、「vector iterators incompatible」というメッセージが表示された。
STLのvectorを利用した際に起こるもので、要素の削除に関連したもの。
前にも何度かやっていて、よく分からずにその当時は投げていた。時間に余裕があるわけではないが、今回はその理由を探ってみた。
プログラムは下記のようなものだ。かなり単純化してはあるが、構造は同じである。
----------------------------------------------------------------
vector v;
v.push_back(10);
v.push_back(-2);
v.push_back(3);
v.push_back(-10);
for(vector::iterator it = v.begin(); it != v.end(); it++){
if(*it < 0){
v.erase(it--);
}
//この後、エラーが起こる
}
----------------------------------------------------------------
「イテレータが不正」とのことなので、とりあえずブレークポイントをしかけてみるものの、「it」には特に問題がない。
そこで試しに、「begin()」と「end()」を取得してみた。
----------------------------------------------------------------
if(*it < 0){
v.erase(it--);
vector::iterator b_it = v.begin();//vの最初の要素を表すはず
vector::iterator e_it = v.end();//vの最後の次の要素を表すはず
}
----------------------------------------------------------------
すると、「b_it」は予想通り最初の要素を表したが、「e_it」は最後の要素を表していた。
本来は最後の次の要素を表さなければならないので、ここで「end()」が狂っていることがわかる。
なぜそうなるのか、詳細は分からないが、結局イテレータでループを回しつつ「erase()」することで問題が出ることは分かった。
ので、ループカウンタを使っての配列アクセスにしつつ削除の際はイテレータを取得して「erase()」するようにした。
結果、エラーは起こらなくなった。詳細については後日調べようと思う。
----------------------------------------------------
for(unsigned int i = 0; i < v.size(); ){
if(v[i] < 0){
vector::iterator it = v.begin() + i;
v.erase(it);
}else{
//erase()は後ろの要素を詰めるので、erase()しなときのみカウンタを回す
i++;
}
}
----------------------------------------------------
上記は修正結果である。
あまり良いプログラムには見えない。
STLのvectorを利用した際に起こるもので、要素の削除に関連したもの。
前にも何度かやっていて、よく分からずにその当時は投げていた。時間に余裕があるわけではないが、今回はその理由を探ってみた。
プログラムは下記のようなものだ。かなり単純化してはあるが、構造は同じである。
----------------------------------------------------------------
vector
v.push_back(10);
v.push_back(-2);
v.push_back(3);
v.push_back(-10);
for(vector
if(*it < 0){
v.erase(it--);
}
//この後、エラーが起こる
}
----------------------------------------------------------------
「イテレータが不正」とのことなので、とりあえずブレークポイントをしかけてみるものの、「it」には特に問題がない。
そこで試しに、「begin()」と「end()」を取得してみた。
----------------------------------------------------------------
if(*it < 0){
v.erase(it--);
vector
vector
}
----------------------------------------------------------------
すると、「b_it」は予想通り最初の要素を表したが、「e_it」は最後の要素を表していた。
本来は最後の次の要素を表さなければならないので、ここで「end()」が狂っていることがわかる。
なぜそうなるのか、詳細は分からないが、結局イテレータでループを回しつつ「erase()」することで問題が出ることは分かった。
ので、ループカウンタを使っての配列アクセスにしつつ削除の際はイテレータを取得して「erase()」するようにした。
結果、エラーは起こらなくなった。詳細については後日調べようと思う。
----------------------------------------------------
for(unsigned int i = 0; i < v.size(); ){
if(v[i] < 0){
vector
v.erase(it);
}else{
//erase()は後ろの要素を詰めるので、erase()しなときのみカウンタを回す
i++;
}
}
----------------------------------------------------
上記は修正結果である。
あまり良いプログラムには見えない。
PR