質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
iteratorパターン

iteratorパターンとは、オブジェクト指向プログラミングのデザインパターンです。コンテナオブジェクトの要素を列挙する手段を独立させることによって、コンテナの内部仕様に依存しない反復子を提供することを目的とします。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Q&A

解決済

3回答

1400閲覧

listのiteratorが破壊されないようにするには

Parsley_068

総合スコア8

iteratorパターン

iteratorパターンとは、オブジェクト指向プログラミングのデザインパターンです。コンテナオブジェクトの要素を列挙する手段を独立させることによって、コンテナの内部仕様に依存しない反復子を提供することを目的とします。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

0グッド

0クリップ

投稿2019/11/30 04:24

##前提・分からない事
シューティングゲームを作ろうとしていて、敵キャラクターの管理をリストで行っています。ゲームはステージ制でステージクリアした際にそのステージのエネミーのリストをイテレーターを使って一度全てデリートしようとしているのですが、うまくいかず、イテレーターが破壊されて例外処理されてしまいます。
イテレーターを破壊せずに一度全ての敵キャラクターのリストを削除するにはどうすればよいでしょうか?

##ソースコード

C++

1class SceneManager 2{ 3private: 4 //一部省略 5 bool goal = false; 6 7 int clear = 2; 8 int stage = 1; 9 10public: 11 12 SceneManager() 13 { 14 sequence.change(&SceneManager::play_stage_1); 15 } 16 17 Player* player; 18 Target* target; 19 20//敵キャラクタークラスのリストとイテレーター 21 std::list<Cat*>cats; 22 std::list<Cat*>::iterator C_it; 23 24 std::list<Rabbit*>rabbits; 25 std::list<Rabbit*>::iterator R_it; 26 27 std::list<Cancer*>cancers; 28 std::list<Cancer*>::iterator K_it; 29 30 31 CSequence<SceneManager>sequence; 32}; 33 34//ソースコードの一部 35 36#define SAFE_DELETE(p) {\ 37 if (p) {\ 38 delete p; \ 39 p = nullptr; \ 40 }\ 41} 42 43C_it = cats.begin(); 44R_it = rabbits.begin(); 45 46while (R_it != rabbits.end()) 47{ 48 if (*target->get_clear()) 49 { 50//ここでイテレーターの破壊が起きる 51 safeDelete(*R_it); 52 rabbits.erase(R_it); 53 continue; 54 } 55 56 R_it++; 57} 58 59 60while (C_it != cats.end()) 61{ 62 (*C_it)->draw(); 63 (*C_it)->move(*player->get_Y(), *player->get_Wait()); 64 65 if (*(*C_it)->get_X() <= -100) 66 { 67//個々の処理だけ問題なくできる 68 SAFE_DELETE(*C_it); 69 C_it = cats.erase(C_it); 70 71 continue; 72 } 73 if (*target->get_clear()) 74 { 75//例外は起きないが固まる 76 SAFE_DELETE(*C_it); 77 C_it = cats.erase(C_it); 78             continue; 79 } 80 81 C_it++; 82 }

##試したこと
別のイテレーターを用意してauto temp = R_it;という風に別のリストに格納したりもしましたが、駄目でした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

こんにちは。

まず、target を初期化していないし、safeDelete()関数は存在しません。問題が発生する最小のソースにすることを強くお勧めします。

1点だけ。
std::listのerase関数は、イテレータがポイントしている要素を削除しているので、そのイテレータは不正な領域をポイントするようになります。従って、R_itはコメントに記載されている通りに壊れます。
C_itのように更新すればよさそうに感じます。

投稿2019/11/30 06:28

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Parsley_068

2019/11/30 07:39

回答ありがとうございます。safeDelete関数なんてないですね・・ご指摘ありがとうございます。 しかし自分にはSAFE_DELETE関数部分以外の部分でC_itとR_itの違いが分かりません・・・よろしければ細かく説明してもらってもよろしいでしょうか。不躾ですいません。あとtargetは書いてないだけで一応初期化はしています。
Chironian

2019/11/30 07:52

> C_itとR_itの違いが分かりません ちゃんと見比べれば直ぐに分かる相違です。思い込みを排除して1文字づつ見比べて見て下さい。 > targetは書いてないだけで一応初期化はしています。 書いていない部分にミスが潜んでいる可能性があります。 デバッグの時は「全てを疑う」が鉄則です。なかなか見つからないバグは、多くのケースで「思わぬところ」に潜んでいます。
Parsley_068

2019/11/30 08:24

R_it = rabbits.erase(R_it);にするべきだったんですね・・なんで気付かなかったんだろう・・・ 上記の通りに修正した所、無事動きました!こんな馬鹿らしい事にも丁寧に回答していただきありがとうございました。
guest

0

例外なく全てであれば、clear();を使うのはいかがでしょうか?
for文を使わないですし、早いかと・・・?

纏めて消す場合はこれで行けるかと。

C++

1 for (auto itr = m_Clist.begin(); itr != m_Clist.end(); ++itr) { 2 Bullet *bullet = (*itr); 3 delete bullet; 4 } 5 m_Clist.clear();

もし何かの処理をしながら、消す場合はこちら。
質問者様の場合、itrがnullptrになっているのが原因かと。
どこを指しているのかわからないのに、○○を消して!とeraseに行ってもどこ!?ってなりますから・・

C++

1 for (auto itr = m_Clist.begin(); itr != m_Clist.end();) { 2 Bullet *bullet = (*itr); 3 bullet->Step(); 4 if (!bullet->IsActive()) { 5 delete bullet; 6 itr = bullet_list_.erase(itr); 7 continue; 8 } 9 ++itr; 10 }

投稿2019/11/30 05:53

編集2019/11/30 07:33
kurara674

総合スコア29

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Parsley_068

2019/11/30 06:25

試してみましたが、ダメでした・・・例外処理はされないものの固まって動かなくなってしまいました。
Parsley_068

2019/11/30 08:21

細かいコードまで書き直してもらいありがとうございます!こちらでも試して問題なく動きました。 最後まで付き合ってもらい本当にありがとうございました。
guest

0

rabbits.erase(R_it)R_it = rabbits.erase(R_it)にしたら大丈夫でした。
今後はツールのインテリジェンス機能に頼りっぱなしではなくスペルなど潜在的にエラーを吐き出す危険性がないか確認しながらデバッグしていきたいと思います。

投稿2019/11/30 08:28

Parsley_068

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問