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

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

新規登録して質問してみよう
ただいま回答率
86.02%
STL

STL(Standard Template Library)は、ジェネティックコンテイナー、イテレーター、アルゴリズム、そして関数オブジェクトのC++ライブラリーです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

C++のlistで、pushしたクラスのメンバ関数から、自分を殺したい

sadora39
sadora39

総合スコア7

STL

STL(Standard Template Library)は、ジェネティックコンテイナー、イテレーター、アルゴリズム、そして関数オブジェクトのC++ライブラリーです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

4回答

0グッド

0クリップ

3259閲覧

投稿2018/05/12 12:00

前提・実現したいこと

listにpushしたクラスを、メンバ関数内で自殺させたいのですが、出来ません。
どうすればこれを実現出来るのでしょうか?

また、調べていて思ったのですが、これ仮に削除出来ても、イテレータのループの所で問題が起きるのでしょうか?
その場合は、どのように対処すればいいのでしょうか?

発生している問題・エラーメッセージ

重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態 エラー C2678 二項演算子 '==': 型 'cEnemy' の左オペランドを扱う演算子が見つかりません (または変換できません) (新しい動作; ヘルプを参照)。 ConsoleTest c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.13.26128\include\list 1548

該当のソースコード

C++

1#include<iostream> 2#include<list> 3 4class cEnemy { 5public: 6 void F(); 7}; 8 9std::list<cEnemy> TestList; 10 11int main() { 12 TestList.push_back(cEnemy()); 13 TestList.push_back(cEnemy()); 14 TestList.push_back(cEnemy()); 15 16 for (auto IT = TestList.begin(); IT != TestList.end(); IT++) { 17 IT->F(); 18 } 19 20 return 0; 21} 22 23void cEnemy::F() { 24 //画面外に出たら、殺す 25 if (true) { 26 TestList.remove(*this); 27 } 28} 29

試したこと

「C2678」でグーグル検索
「C++ list 自分 削除」でグーグル検索

補足情報(FW/ツールのバージョンなど)

OS:Windows10
コンパイラ:VisualStudio2017
言語:C++

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答4

1

こんにちは。

そのコードの場合、TestList.remove(*this);の呼び出しの中で、cEnemyのデストラクタが呼ばれます。
つまり、remove()から返ってきた時点で、thisがあらぬところを指しています。
非常に危険なプログラミングですので、できるだけ避けた方が良いです。
F()は削除するかどうかのみ返却し、戻ってきてからremoveすることをお勧めします。

次に、コンテナを枚挙するループの中でコンテナの要素を削除するとハマることが非常に多いです。
これもお勧めしませんが、各種stlコンテナでのループ中の要素の削除に対処例がありました。

なお、std::remove_ifを使うのでも良いのですが、削除するべき要素を先頭に集める際にstd::listでもコピー(ムーブ対応したクラスならムーブ)するのでちょっと頭痛いかも。

投稿2018/05/12 12:47

Chironian

総合スコア23251

KSwordOfHaste👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

ベストアンサー

自殺するオブジェクトが自分が住んでるビルをハードコーディングして部屋ごと爆破するのは
なんというか迷惑な気がする。

案1. 死体掃除業者を呼ぶ

c++

1#include<iostream> 2#include<list> 3 4class cEnemy { 5 bool alive = true; 6public: 7 bool isAlive() const; 8 void F(); 9}; 10 11std::list<cEnemy> TestList; 12 13int main() { 14 TestList.push_back(cEnemy()); 15 TestList.push_back(cEnemy()); 16 TestList.push_back(cEnemy()); 17 18 for (auto IT = TestList.begin(); IT != TestList.end(); IT++) { 19 IT->F(); // 殺す 20 } 21 std::cout << TestList.size() << std::endl; 22 // お片付け 23 TestList.remove_if([](const cEnemy& e){return !e.isAlive();}); 24 std::cout << TestList.size() << std::endl; 25 return 0; 26} 27 28void cEnemy::F() { 29 //画面外に出たら、殺す 30 if (true) { 31 alive = false; // 死にました 32 } 33} 34bool cEnemy::isAlive() const{return alive;}

案2. ビル(list)に管理人を雇ってそいつに命令する。

c++

1class cEnemy { 2 bool alive = true; 3public: 4 bool isAlive() const; 5 bool F(); 6}; 7 8class cEnemyManager { 9public: 10 std::list<cEnemy> TestList; 11 void remove_if_F(); 12} 13 14void cEnemyManager::remove_if_F(){ 15 TestList.remove_if( 16 [](cEnemy& e){return e.F();} 17 ); 18} 19bool cEnemy::F() { 20 //画面外に出たら、殺す 21 if (true) { 22 alive = false; // 死にました 23 return true; 24 } 25 return false; 26}

投稿2018/05/12 15:26

編集2018/05/12 15:52
asm

総合スコア15141

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

sadora39

2018/05/12 23:37

回答してくれた皆さんありがとうございました。 とても参考になりました。 この方の案1を使いたいと思います。

0

メンバ関数内で自殺

とありますが、このためには当該メソッド内で以下のことができなければなりません。
0. 画面外であることの判定
0. 当該リストからの自身を除外
0. 自身の使用するメモリ領域の解放

本課題の場合、2番目についてはグローバル変数なので可能ですが、一般にこれらの要件を満たすことは結構難しいです(とくに3番目)。もちろん完全に不可能というわけではありませんが、要素側で自殺するよりも、リスト側に機能追加するアプローチを考えた方が楽だと思います。

投稿2018/05/12 13:19

HogeAnimalLover

総合スコア4823

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

vector<T>::remove はコンテナの中から等しい要素を探して削除するので、
等しい(==)か否かが判定できにゃならんです。

C++

1#include<iostream> 2#include<list> 3 4class cEnemy { 5 int id_; 6public: 7 cEnemy(int id) : id_(id) {} 8 ~cEnemy() { std::cout << id_ << ": dead\n"; } 9 int id() const { return id_; } 10 void F(); 11}; 12 13// 等しければtrue 14inline bool operator==(const cEnemy& x, const cEnemy& y) { 15 return x.id() == y.id(); 16} 17 18std::list<cEnemy> TestList; 19 20int main() { 21 TestList.emplace_back(0); 22 TestList.emplace_back(1); 23 TestList.emplace_back(2); 24 25 // コンテナから削除されるかもしれんので、iteratorは使えない 26 while ( !TestList.empty() ) { 27 TestList.back().F(); 28 } 29 30 return 0; 31} 32 33void cEnemy::F() { 34 //画面外に出たら、殺す 35 if (true) { 36 TestList.remove(*this); 37 } 38}

...とはいえこんな危ういコードは書くべきではない。
自分自身を抹殺するより、殺し屋を雇うが吉かと。

投稿2018/05/12 12:35

編集2018/05/12 13:27
episteme

総合スコア16009

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

STL

STL(Standard Template Library)は、ジェネティックコンテイナー、イテレーター、アルゴリズム、そして関数オブジェクトのC++ライブラリーです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。