忍者ブログ
AdminWriteComment
プログラミング、ゲームシステムなど普段考えたことについてのメモ帳代わり。
No.
2025/06/20 (Fri) 17:11:52

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

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++;
 }
}

----------------------------------------------------

 上記は修正結果である。

 あまり良いプログラムには見えない。
PR
[14]  [13]  [12]  [11]  [10]  [9]  [8]  [7]  [6]  [5]  [4
カレンダー
05 2025/06 07
S M T W T F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
フリーエリア
最新コメント
最新トラックバック
プロフィール
HN:
kamiyama
性別:
男性
自己紹介:
学生。ヘタレゲームプログラマ。
バーコード
ブログ内検索
P R
アクセス解析
アクセス解析
忍者ブログ [PR]