0

私の C++ コードに非常に奇妙な点があることに気付きました。

class A
{
    public:
    void doIt(){cout<<"hello"<<endl;}
};
int main() {
    A* a=new A();
    A* b=a;
    delete a;
    b->doIt();
    return 0;
}

deleteヒープからメモリを消去してb->doIt()失敗すると思いました。しかし、このコードを実行している間は機能し、「hello」も表示されます。

なんで?

4

2 に答える 2

4

削除するとヒープからメモリが消去されると思いました

メモリを「消去」できる唯一の方法は、ハンマーを使用することです。

メモリは「未使用」としてマークされ、オブジェクトは意味的に破棄されます。

そしてb->doIt()失敗するでしょう

なぜですか?

あなたのためにそれを行うためのメカニズムはありませんし、一般的なケースではありえません。

存在しないオブジェクトに対して関数を呼び出さないことは、あなたの責任です。

doIt実際には、オブジェクトのメモリに実際にアクセスしようとするものは何もないため、ここではクラッシュしません。関数はオブジェクトの「中に」保存されないことを覚えておいてください — それはあなたのプログラムの一部であり、あなたのプログラムはまだ存在しています。

オブジェクトの状態にアクセスしたり変更したりしても、そのメモリがまだdoItアクティブなページにある限り、おそらくクラッシュすることはありません。これがまさに、未定義の動作が予測不可能であると定義されている理由です。

避ける。


于 2016-02-18T11:56:50.947 に答える
1

doItメソッドが A クラスの内部状態を使用していないことが原因である可能性が最も高いです。したがって、コンパイラはおそらくそれを静的メソッドに最適化し、呼び出しは静的クラス コンテキストで呼び出されます。ポインターがぶら下がっているという事実は、メソッドの実行を妨げません。

ただし、これは未定義の動作であり、より厳密なコンパイラでは、実際に失敗するコードが実際に生成される可能性があります。

于 2016-02-18T11:45:24.373 に答える