2

これを削除する動作を確認するためのサンプルプログラムを作成しました

class A
 {
   ~A() {cout << "In destructor \n ";}
 public: 
    int a;
    A() {cout << "In constructor \n ";}

    void fun()
     {
       cout << "In fun \n";
       delete this;
       cout << this->a << "\n"; // output is 0
       this->fun_2(); // how m able to call fun_2, if delete this is called first ??
     }

   void fun_2()
    {
      cout << "In fun_2 \n";
    }

main()
{
 A *ptr = new A;
 ptr->a = 100;
 ptr->fun(); //delete this will be executed here
 ptr->fun_2(); //how m able to execute fun_2 when this pointer is deleted ??
 cout<< ptr->a << "\n"; //prints 0
 return 0;
}

> Output
In constructor
In fun
In destructor
0
In fun 2
In fun 2
0

質問

  1. fun()でdelete thisを実行した後、fun()でこのポインタを使用してfunc_2()にアクセスするにはどうすればよいですか?
  2. 主に、このポインタが削除されたときにobj->fun_2を実行する方法は??
  3. このオブジェクトを強制終了した後に関数メンバーにアクセスできる場合、データメンバーがゼロ「0」になっているのはなぜですか?

Linuxubuntuとg++コンパイラを使用するm

4

2 に答える 2

9
  1. 表示されるのは未定義の動作です。動作するか、クラッシュする可能性があります。
  2. ポインタは削除されたインスタンスを指しています-それはダングリングポインタです。
  3. これも未定義の動作です。ゼロまたはガベージ値が表示される場合があります。

Eric Lippertは、関数が戻った後のローカル変数へのポインターに関する質問への回答で、非常に優れた「ホテルの部屋のテーブルの引き出しにある本」のアナロジーを提供しました。これはここでも同様に適用できます。

于 2012-08-09T16:21:48.907 に答える
2

それを同様のシナリオと比較してみましょう。

A *a= new A();  
func(a);  
delete a;  
func2(a);  

私のサンプルでは、​​コンパイラはポインタaをfuncとfunc2に渡すだけで、有効なオブジェクトを指しているかどうかは関係ありません。したがってfunc2(a)、func2を呼び出してポインタを逆参照する場合、これは未定義の動作です。メモリがオペレーティングシステムに解放され、プログラムが* aにアクセスできなくなった場合、プログラムがクラッシュする可能性があります。通常、deleteはメモリを割り当てたままにし、オペレーティングシステムに戻さないため、deleteの後に* aにアクセスしても例外は発生せず、任意の値が返されます。delete aこれは*aの以前の値である可能性がありますが、deleteの実装や、との間で行われるnewへの他の呼び出しに応じて、他の値になる可能性もあります*a。たとえば、MSVCは、デバッグモードでメモリを事前定義されたパターンに設定するため、解放されたメモリにアクセスするときに簡単に見つけることができます。

なぜこれがあなたの質問に関係しているのですか?コンパイラはthis隠された暗黙のパラメータとして渡されるためです。

于 2012-08-09T16:30:32.187 に答える