2

SOの定数参照の存続期間についていくつか質問がありますが、それでもわかりません。

このコードは有効ですか?

struct S
{
    const int &ref;
    S( const int &x ) : ref(x) { }
};

int main( )
{
    S s( 0 );
    // ...
    use( s.ref );
    // ...
    return 0;
}

式( )が評価された0後に期限切れになるはずなので、直感的にはノーと言います。S s(0);

ただし、GCCとCLANGはどちらも警告なしに正常にコンパイルされ、valgrindはランタイムエラーを検出しません。

参照について何が欠けていますか?

4

5 に答える 5

4

12.2/4 によると、私には無効に思えます:

完全な式の終わりとは異なる時点で一時変数が破棄される状況が 2 つあります。最初のコンテキストは 、オブジェクトを定義する宣言子の初期化子として式が現れる場合です。そのコンテキストでは、式の結果を保持するテンポラリは、オブジェクトの初期化が完了するまで持続します

一時的なものは、呼び出されるs時点までではなく、完全に構築されるまでのみ有効になります。use

于 2010-12-23T22:29:12.013 に答える
2

他の人が指摘しているように、C++ 標準は0、コンストラクターを呼び出す間、コンパイラーに一時的なものを保持することのみを強制します。実際には、gcc はmain関数の実行中は一時的に保持し、プログラムが期待どおりに実行されるようにします。このため、警告や実行時エラーは発生しません。

しかし、これは偶然にしか機能しません。この動作に依存しないでください。

于 2010-12-23T23:02:29.500 に答える
1

ここで注意すべきことは、ではconstなく参照です。const は、静的分析のための単なるツールです。参照は噛む可能性があるため、注意が必要です。

int& f()
{
    int i = 2;
    return i;
}

コンパイラは、実行時に発生する問題について警告するほど賢い場合もありますが、そうでない場合もあります。いずれにせよ、コンパイラはこれについて警告する必要はありません

于 2010-12-23T22:38:09.193 に答える
1

これは、valgrind でさえ不平を言うコードの別の微調整です。

#include <iostream>

struct S
{
    const int &ref;
    S( const int &x ) : ref(x) { }
};

S* foo()
{
    return new S(0);
}

int main( )
{
    S* s = foo();
    std::cout << s->ref << std::endl;
    return 0;
}

これは通常、関数のスタック フレームに一時的なものを配置fooするため、その関数が戻ると破棄されます。これは、ローカル変数のアドレスを返すことに似ています。

他の回答は、コンパイラがこれを行うことが許可されている理由を指摘しています。私のコードは単なる例です。

于 2010-12-23T23:28:55.583 に答える
0

0一時的ではなく、リテラルです。プログラムに次の小さな変更を加えてみてください。

struct S 
{
    const int &ref;
    S( const int &x ) : ref(x) { }
};

int f()
{
    return 0;
}

int main( )
{
    S s( f() );
    // ...
    use( s.ref );
    // ...
    return 0;
}

一時的な参照のルールは、メンバーではなくローカル変数に対してのみ機能すると思います。

于 2010-12-23T22:29:51.280 に答える