5

const参照を処理する次のコードについて考えてみます。

const int & func (const int &x)
{
    return x;
}

struct Foo {
    Foo (const int &x)
    : m_x(x) {}

    const int & getX ()
    { return m_x; }

    const int &m_x;
};

次のうち、現在許可されているものがある場合は、それを知りたいのですが。

int x = func(int(7));
int y = Foo(int(7)).getX();

割り当てまたは?intによって使用される前に一時オブジェクトがまだ存在するという保証はありますか?getX

更新:これは安全なようですが、なぜ正確なのですか?

  1. 一時的なものはconst参照に再帰的にバインドされ、それらへのバインドされた参照が存在する限り存在することが保証されているためですか?
  2. それとも、完全な表現の期間中、それらが存在することが保証されているからですか?

参照の代わりにポインタを格納するエッジケースを考えてみましょう。

struct Foo {
    Foo (const int &x)
    : m_x(&x) {}

    const int & getX ()
    { return *m_x; }

    const int *m_x;
};

int y = Foo(int(7)).getX();

ケース1)が正しければ、これは機能しないようです。しかし、ケース2)が正しければ、そうなるでしょう。

4

2 に答える 2

7

xとに値をコピーするため、どちらも安全ですy。一時的なものは、完全な式が終了するまで有効です。

12.2一時的なオブジェクト

4)完全な式の終わりとは異なる時点で一時的なものが破棄される2つのコンテキストがあります。最初のコンテキストは、配列の要素を初期化するためにデフォルトのコンストラクターが呼び出されたときです。コンストラクターに1つ以上のデフォルトの引数がある場合、デフォルトの引数式で作成された一時的なものは、コンストラクターから戻った直後に破棄されます。

5)2番目のコンテキストは、参照が一時的なものにバインドされている場合です。参照がバインドされている一時オブジェクト、または参照がバインドされているサブオブジェクトの完全なオブジェクトである一時オブジェクトは、以下に指定されている場合を除き、参照の存続期間中存続します。コンストラクターのctor-initializer(12.6.2)の参照メンバーへの一時的なバインドは、コンストラクターが終了するまで持続します。関数呼び出し(5.2.2)の参照パラメーターへの一時的なバインドは、呼び出しを含む完全な式が完了するまで持続します。関数の戻り値ステートメント(6.6.3)の戻り値への一時的なバインドは、関数が終了するまで持続します。これらすべての場合において、参照がバインドされている一時的なものを除いて、参照を初期化する式の評価中に作成された一時的なものは、それらが作成された完全な表現の終わりに、そしてそれらの構築の完了の逆の順序で破壊されます。参照がバインドされている2つ以上の一時的なものの存続期間が同じポイントで終了する場合、これらの一時的なものは、構築の完了とは逆の順序でその時点で破棄されます。さらに、参照にバインドされた一時的な破棄では、静的または自動の保存期間(3.7.1、3.7.2)を持つオブジェクトの破棄の順序を考慮に入れる必要があります。つまり、obj1が、一時が作成される前に作成された静的または自動ストレージ期間を持つオブジェクトである場合、一時はobj1が破棄される前に破棄されるものとします。obj2が、一時的なものが作成された後に作成された静的または自動の保管期間を持つオブジェクトである場合、obj2が破棄された後、一時的なものは破棄されます。[ 例:

class C 
{ 
/ / ... 
public : 
    C(); 
    C(int ); 
    friend C operator +(const C&, const C&); 
    ~C(); 
}; 
C obj1 ; 
const C& cr = C (16)+ C (23); 
C obj2 ; 

式C(16)+ C(23)は、3つの一時的なものを作成します。式C(16)の結果を保持する最初の一時T1、式C(23)の結果を保持する2番目の一時T2、およびこれら2つの式の加算の結果を保持する3番目の一時T3。次に、一時的なT3が参照crにバインドされます。T1とT2のどちらを最初に作成するかは指定されていません。T1がT2の前に作成される実装では、T2がT1の前に破棄されることが保証されます。一時的なT1とT2は、operator+の参照パラメーターにバインドされます。これらの一時的なものは、operator+の呼び出しを含む完全な式の最後で破棄されます。参照crにバインドされた一時的なT3は、crの存続期間の終わり、つまりプログラムの終わりに破棄されます。加えて、T3が破棄される順序は、静的ストレージ期間を持つ他のオブジェクトの破棄順序を考慮に入れています。つまり、obj1はT3の前に構築され、T3はobj2の前に構築されるため、obj2はT3の前に破棄され、T3はobj1の前に破棄されることが保証されます。—例を終了]

于 2012-09-23T11:27:47.273 に答える
1

どちらも安全です。一時はconst参照にバインドでき、一時がバインドされている式が実行されるまで続きます。この場合、コンストラクター引数をバインドし、コンストラクターの閉じ中括弧まで存続します。

const類似の現象は、参照へのデフォルトの関数引数として一時的なものを使用することです。

void foo(const someclass& bla = someclass()); // bind const ref with default constructed someclass
于 2012-09-23T11:28:49.593 に答える