2
#include <stdio.h>

class Foo {

        public:
                Foo(char x);
                Foo(char x, int y);
                ~Foo();
                void abc();
                void dev();
};

void Foo::dev()
{

        printf("inside dev \n");
}

void Foo::abc()
{

        printf("inside abc \n");
        delete this;
        dev();
}

Foo::Foo(char x)
{

      printf("inside 1 argu const---------------");

}

Foo::~Foo()
{

    printf("inside 1 argu dest---------------");
}

#include "test.h"

int main()
{

        Foo *obj=new Foo('a');
        printf("%u inside main\n", obj);
        obj->abc();
        return 0;
}

プログラムの出力を見ると、devを呼び出す前に関数abcで「deletethis」が呼び出されているにもかかわらず、「dev」関数がまだ呼び出されているようです。gcc / g ++はこれをどのように処理しますか?

4

7 に答える 7

12

オブジェクトは、未定義の時間はまだ使用可能である可能性があります。また、delete問題のポインタには影響しません。

Deleteオブジェクトインスタンスでデストラクタを呼び出すだけです。Deleteメモリをプールに返しますが、このメモリがいつ再利用されるか(あるとしても)については未定義(およびランタイム関連)です。オブジェクトは、プログラムの残りの期間中は非常によく利用できますが、重要なのは、それを当てにしないでください

注意すべきそれほど明白な落とし穴はありません。オブジェクトには、動的に割り当てられたかどうかを知る方法がありません。したがって、オブジェクトが静的に割り当てられた呼び出しである場合、そのオブジェクトでdelete this問題が発生することがわかります。ただし、上記の場合はそうではありません。

于 2010-01-15T13:04:22.793 に答える
6

Delete はメモリの割り当てを解除するだけです (デストラクタも呼び出します)。基本的に、ごみ箱thisポインターを使用して dev を呼び出しました。これは、dev が仮想ではなく、メンバー変数にアクセスしようとしないためにのみ機能します。そうしないと、他の無効なポインターを使用するのと同じようにアクセス違反になる可能性があります。

于 2010-01-15T13:06:35.763 に答える
2

gcc/g++ はこれをどのように処理しますか?

テストからわかるように、それを処理します。

ただし、危険です。たとえばdev、Foo クラスのインスタンス メンバー データにアクセスするようにメソッドを変更した場合、その動作 (つまりdev、Foo インスタンスが削除された後にメソッドを呼び出す) は不正になり、動作は未定義になります。実際の動作は、プログラムの他の場所で何が起こっているかによって異なります。たとえば、Foo インスタンスが占有していた (および Foo インスタンスが削除されたときに解放された) メモリが別のスレッドによって再割り当てされたかどうかなどです。

devメソッドが仮想メソッドであり、Foo が基本クラスまたは継承階層のサブクラスである場合も、動作は異なります。

dev静的メソッドとして定義した方がよいでしょう:

class Foo {

public:
    Foo(char x);
    Foo(char x, int y);
    ~Foo();
    void abc();
    static void dev();
};

静的として定義できない関数を呼び出す場合 (仮想関数であるか、インスタンス メンバー データにアクセスするため)、行っていたことを実行するのは違法です。

于 2010-01-15T13:08:15.280 に答える
1

dev();この時点で呼び出されると予想されますが、thisポインターが破棄されたオブジェクトを指しているため、未定義の動作です。あなたの呼び出しが成功しているように見える理由は、あなたが幸運になり、this呼び出し時に が指すメモリを他に何も要求していないためです。dev()そうでなければ、結果は控えめに言っても「興味深い」でしょう。

于 2010-01-15T13:07:06.953 に答える
1

delete this通常、 this ポインター自体には影響しないため、引き続き関数を呼び出すために使用できます。ただし、この動作は定義されていません。動作する場合と動作しない場合があります。一般に、delete thisC++ では悪い考えです。それを使用する唯一の理由は、いくつかの参照カウントクラスであり、その使用を必要としない参照カウントへのより良いアプローチがあります。

于 2010-01-15T13:07:39.197 に答える
1

Delete は、クラスのコードまたは静的変数を削除せず、インスタンス変数のみを削除します。ただし、他の人が指摘したように、オブジェクト ポインターを削除した後にオブジェクト ポインターを使用して得られる動作は未定義です。

しかし、これを自問してください (または、stackoverflow に尋ねてください ;-): クラスのインスタンスが存在しない場合、クラスの静的メンバー関数を呼び出すことはできますか? (もちろん、答えはイエスです。)

dev() が静的である場合、このコードは完全に合法です。

于 2010-01-15T13:13:54.303 に答える
0

デストラクタdeleteを呼び出すだけですoperator delete(クラスにオーバーライドがない場合は組み込みバージョン)。より賢くはありませfree()ん。削除されたオブジェクトの使用を妨げるものは何もありません。うまくいきませんよ、確かに。

通話delete this;もかなり危険です。その時点からオブジェクトは有効ではなくなり、メソッドを呼び出したり、メンバーにアクセスしようとすると、未定義の操作領域になります。

于 2010-01-15T13:05:39.343 に答える