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

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

ただいまの
回答率

90.84%

  • C++

    3133questions

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

  • STL

    13questions

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

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

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 154

sadora39

score 1

 前提・実現したいこと

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

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

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

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

 該当のソースコード

#include<iostream>
#include<list>

class cEnemy {
public:
    void F();
};

std::list<cEnemy> TestList;

int main() {
    TestList.push_back(cEnemy());
    TestList.push_back(cEnemy());
    TestList.push_back(cEnemy());

    for (auto IT = TestList.begin(); IT != TestList.end(); IT++) {
        IT->F();
    }

    return 0;
}

void cEnemy::F() {
    //画面外に出たら、殺す
    if (true) {
        TestList.remove(*this);
    }
}

 試したこと

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

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+1

こんにちは。

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

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

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

#include<iostream>
#include<list>

class cEnemy {
    bool alive = true;
public:
    bool isAlive() const;
    void F();
};

std::list<cEnemy> TestList;

int main() {
    TestList.push_back(cEnemy());
    TestList.push_back(cEnemy());
    TestList.push_back(cEnemy());

    for (auto IT = TestList.begin(); IT != TestList.end(); IT++) {
        IT->F(); // 殺す
    }
    std::cout << TestList.size() << std::endl;
    // お片付け
    TestList.remove_if([](const cEnemy& e){return !e.isAlive();});
    std::cout << TestList.size() << std::endl;
    return 0;
}

void cEnemy::F() {
    //画面外に出たら、殺す
    if (true) {
      alive = false; // 死にました
    }
}
bool cEnemy::isAlive() const{return alive;}

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

class cEnemy {
    bool alive = true;
public:
    bool isAlive() const;
    bool F();
};

class cEnemyManager {
public:
    std::list<cEnemy> TestList;
    void remove_if_F();
}

void cEnemyManager::remove_if_F(){
    TestList.remove_if(
      [](cEnemy& e){return e.F();}
    );
}
bool cEnemy::F() {
    //画面外に出たら、殺す
    if (true) {
      alive = false; // 死にました
      return true;
    }
    return false;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/13 08:37

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

    キャンセル

0

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

#include<iostream>
#include<list>

class cEnemy {
    int id_;
public:
    cEnemy(int id) : id_(id) {}
    ~cEnemy() { std::cout << id_ << ": dead\n"; }
    int id() const { return id_; }
    void F();
};

// 等しければtrue
inline bool operator==(const cEnemy& x, const cEnemy& y) {
  return x.id() == y.id();
}

std::list<cEnemy> TestList;

int main() {
    TestList.emplace_back(0);
    TestList.emplace_back(1);
    TestList.emplace_back(2);

    // コンテナから削除されるかもしれんので、iteratorは使えない
    while ( !TestList.empty() ) {
        TestList.back().F();
    }

    return 0;
}

void cEnemy::F() {
    //画面外に出たら、殺す
    if (true) {
        TestList.remove(*this);
    }
}

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

メンバ関数内で自殺

とありますが、このためには当該メソッド内で以下のことができなければなりません。

  1. 画面外であることの判定
  2. 当該リストからの自身を除外
  3. 自身の使用するメモリ領域の解放

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • C++

    3133questions

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

  • STL

    13questions

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