0

重複の可能性:
ローカル変数のメモリにそのスコープ外でアクセスできますか?
C++ コンストラクター: const 参照の初期化中のガベージ

この質問は、私が以前に尋ねた別の質問「PImpl の代わりに不透明な参照。可能ですか?」に直接関連しています。.

コンストラクターで一時変数に初期化される他のクラスの参照メンバーを持つクラスがあるとします。

#include <iostream>

struct B
{
    B(int new_x = 10) : x(new_x) { std::cout << "B constructed\n"; }
    ~B() { std::cout << "B destroyed\n"; }

public:
    int x;
};

struct A
{
    A()
    : b( B(23) )
    {
        std::cout << "A constructed\n";
    }

    void Foo()
    {
        std::cout << "A::Foo()\n";
    }

    ~A()
    {
        std::cout << "A destroyed\n";
    }

public:
    const B& b;
};

int main()
{
    A a;
    a.Foo();
    cout << "x = " << a.b.x << endl;
}

上記のコードを実行すると、出力は次のようになります。

B constructed
B destroyed
A constructed
A::Foo()
x = 23
A destroyed

一時が破棄されて参照メンバーが無効になったとしても、参照メンバーの整数フィールドは引き続き読み取り可能です。なぜそれはまだ機能しますか?

4

3 に答える 3

1

参照が無効である場合、それはそれが読めないという意味ではありません。これは、有効なオブジェクトを参照していないことを意味します。アクセス可能なメモリの一部を参照する場合と参照しない場合があります。含まれている場合は、メモリに以前そこにあったオブジェクトの残骸が含まれていることがわかる場合と見つからない場合があります。

要約すると、動作は未定義です。

于 2012-09-26T13:36:28.477 に答える
1

未定義の動作。あなたの場合、一時的に以前に占有されていたメモリが、B参照する前に上書きされないことが起こります。次にプログラムを実行すると、何かが起こる可能性があります。

表面的に似ていることに注意してください

const B &b = B();

定義された動作があります。一時オブジェクトの有効期間は、B参照バインディングによって延長されます。これは、参照メンバーではなく、参照変数にのみ適用されます。

于 2012-09-26T13:35:30.690 に答える
1

一時的に割り当てられたメモリBは無効になりましたが、他の用途には使用されていません。そのため、読み取りは前回そこにあった値を生成します。ただし、これは未定義の動作です。valgrind を実行すると、エラーの場所が特定されるはずです。

「どうすればいいのか」と疑問に思っている場合は、非常によく似た状況で何が起こるかを説明する素晴らしい答えがあります.

于 2012-09-26T13:38:56.533 に答える