188

なぜこれを行うのですか:

#include <string>
#include <iostream>
using namespace std;

class Sandbox
{
public:
    Sandbox(const string& n) : member(n) {}
    const string& member;
};

int main()
{
    Sandbox sandbox(string("four"));
    cout << "The answer is: " << sandbox.member << endl;
    return 0;
}

次の出力を与える:

答えは次のとおりです。

それ以外の:

答えは:4

4

6 に答える 6

180

ローカル 参照のみconstが寿命を延ばします。

この規格は、参照宣言の初期化子に関するセクションである§8.5.3/ 5、[dcl.init.ref]でそのような動作を指定しています。この例の参照はコンストラクターの引数nにバインドされており、オブジェクトnがバインドされてスコープ外になると無効になります。

有効期間の延長は、関数の引数を介して推移的ではありません。§12.2/5[class.temporary]:

2番目のコンテキストは、参照が一時的なものにバインドされている場合です。参照がバインドされている一時オブジェクト、または一時がバインドされているサブオブジェクトの完全なオブジェクトである一時オブジェクトは、以下に指定されている場合を除き、参照の存続期間中存続します。コンストラクターのctor-initializer(§12.6.2[class.base.init])の参照メンバーへの一時的なバインドは、コンストラクターが終了するまで持続します。関数呼び出し(§5.2.2[expr.call])の参照パラメーターへの一時的なバインドは、呼び出しを含む完全な式が完了するまで持続します。

于 2010-05-06T20:36:24.850 に答える
30

何が起こったのかを説明する最も簡単な方法は次のとおりです。

main() で文字列を作成し、それをコンストラクターに渡しました。この文字列インスタンスは、コンストラクター内にのみ存在していました。コンストラクター内で、このインスタンスを直接指すようにメンバーを割り当てました。スコープがコンストラクターを離れたときに、文字列インスタンスが破棄され、メンバーが存在しなくなった文字列オブジェクトを指していました。Sandbox.member がそのスコープ外の参照を指すようにしても、これらの外部インスタンスはスコープ内に保持されません。

希望する動作を表示するようにプログラムを修正する場合は、次の変更を行います。

int main()
{
    string temp = string("four");    
    Sandbox sandbox(temp);
    cout << sandbox.member << endl;
    return 0;
}

temp は、コンストラクターの最後ではなく、main() の最後でスコープ外に渡されるようになりました。ただし、これは悪い習慣です。メンバー変数は、インスタンスの外部に存在する変数への参照であってはなりません。実際には、その変数がいつスコープ外になるかはわかりません。

私がお勧めするのは、Sandbox.member を として定義することです。const string member;これにより、メンバー変数を一時パラメーター自体として割り当てる代わりに、一時パラメーターのデータがメンバー変数にコピーされます。

于 2010-05-06T21:02:38.150 に答える
5

技術的に言えば、このプログラムは実際に標準出力 (最初はバッファリングされたストリーム) に何かを出力する必要はありません。

  • cout << "The answer is: "ビットはstdout のバッファに出力さ"The answer is: "ます。

  • 次に、ビットは未定義の動作<< sandbox.memberを引き起こすダングリング参照をoperator << (ostream &, const std::string &)に提供します。

このため、何も起こらないという保証はありません。プログラムは一見正常に動作するか、stdout をフラッシュすることなくクラッシュする可能性があります。つまり、「答えは:」というテキストが画面に表示されないということです。

于 2015-05-09T15:28:31.883 に答える
0

Sandboxコンストラクターが戻ると一時文字列がスコープ外になり、それによって占有されていたスタックが他の目的で再利用されたためです。

一般に、参照を長期間保持しないでください。参照は、クラスメンバーではなく、引数またはローカル変数に適しています。

于 2010-05-06T20:36:39.060 に答える