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

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

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

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

C++

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

Q&A

解決済

4回答

3536閲覧

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

sadora39

総合スコア7

STL

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

C++

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

0グッド

0クリップ

投稿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++

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

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

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

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

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

guest

回答4

0

こんにちは。

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

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

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

投稿2018/05/12 12:47

Chironian

総合スコア23272

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

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

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

総合スコア15147

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

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

sadora39

2018/05/12 23:37

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

0

メンバ関数内で自殺

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

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

投稿2018/05/12 13:19

HogeAnimalLover

総合スコア4830

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

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

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

総合スコア16614

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問