-4

以下の強調された行をコメントアウトすると、コンソールに 777 が表示されます。そうしないと、(-534532345) のようなガベージが発生します。私の環境は Microsoft Visual Studio 2012 Pro です。

class C
{
public:
    C () { x = 777; }
    void ou() {cout << x;}
protected:
    int x;
};

class A
{
public:
    A(C & rrc) : rc(rrc) {};
    void koo () {rc.ou();}
protected:
    C & rc;
};

int _tmain(int argc, _TCHAR* argv[])
{
    C c;
    C * pc = new C;
    A a(*pc);
    delete pc; // <<<< this line
    a.koo();

    return 0;
}

この動作が見られる理由を理解するのを手伝ってくれる人はいますか?

4

4 に答える 4

7

a.koo()を呼び出した時点で、そのrc参照が参照している基になるオブジェクトを削除しました。もちろんUBです。次に起こることは、特定のコンパイルに対して特定のプラットフォームで一貫した動作をする可能性があり、777を出力することさえあります(実際には、基になるオブジェクトがごく最近削除されたため、777を出力する可能性があります)。あなたの場合、以前に_tmain()に割り当てられていたメモリのいずれかがpcオブジェクトが上書きされた他の何かに再割り当てされているか、メモリアロケータが削除/解放されたメモリを固定値(通常はゼロ以外ですべてではない)で明示的に上書きするデバッグビルドを使用していますが、0xAAAAAAAAや0xDEADDEAD。-534532345は0xE023AF07(または0xFFFFFFFFE023AF07)なので、前者だと思います(メモリは上書きされた他の何かに割り当てられています)。あなたの例のa.koo()の呼び出しはすぐ後に続くdelete pcので、それがすでにすぐに上書きされているのは驚くべきことですが、UBであるため、技術的には何でも可能です。

于 2013-02-27T23:08:18.067 に答える
4

削除すると、ぶら下がっている参照が残り、それに従うと、未定義の動作につながります。これは、C++またはMSVSの穴ではありません。この言語では、多くの違法行為をチェックせずに、UBを呼び出さないようにプログラマーに任せています。

于 2013-02-27T23:08:28.900 に答える
4

コードの動作は未定義です。存在しなくなったオブジェクトの参照を保持しています。したがって、rc.ou()動作は定義されていません。

于 2013-02-27T23:08:30.100 に答える
1

pcを削除すると、A :: rcはガベージの場所とrc.ou()を指します。ゴミも出力します。これは予想される動作であり、使用しているコンパイラに関係なくこれを実行します

ところで、99 [.99]%の確率で、コンパイラにバグを見つけたと思いますが、それは本当にあなたのバグです。

于 2013-02-27T23:08:54.030 に答える