Const Referenceクラスのメンバーは、一時的な寿命を延ばしますか?
-
03-10-2019 - |
質問
なぜこれをするのか:
#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;
}
の出力を与える:
答えは次のとおりです。
それ以外の:
答えは次のとおりです
解決
それだけ ローカル const
参考文献は寿命を延ばします。
標準は、§8.5.3/5 [dcl.init.ref]、参照宣言の初期化剤に関するセクションでそのような動作を指定します。あなたの例の参照は、コンストラクターの議論に縛られています n
, 、およびオブジェクトのときに無効になります n
範囲外になります。
生涯拡張は、関数引数を介して推移的ではありません。 §12.2/5 [class.temporary]:
2番目のコンテキストは、参照が一時に拘束される場合です。参照が拘束される一時的または、以下に指定されている場合を除き、参照の寿命のために一時的な拘束が持続するサブオブジェクトの完全なオブジェクトである一時的な一時。コンストラクターのCTORイニタライザー(§12.6.2[class.base.init])内の参照メンバーへの一時的な拘束は、コンストラクターが出るまで持続します。関数呼び出し(§5.2.2[expr.Call])の参照パラメーターに一時的にバインドされているのは、コールを含む完全な式が完了するまで続きます。
他のヒント
何が起こったのかを説明する最も簡単な方法は次のとおりです。
main()では、文字列を作成し、コンストラクターに渡しました。この文字列インスタンスは、コンストラクター内にのみ存在していました。コンストラクターの内部では、メンバーを割り当てて、このインスタンスを直接指すようにしました。 Scopeがコンストラクターを離れたとき、文字列インスタンスが破壊され、メンバーはもはや存在しない文字列オブジェクトを指しました。 sandbox.memberを持つことは、その範囲外の参照をポイントしても、それらの外部インスタンスを範囲に保持しません。
プログラムを修正して希望する動作を表示する場合は、次の変更を行います。
int main()
{
string temp = string("four");
Sandbox sandbox(temp);
cout << sandbox.member << endl;
return 0;
}
これで、TEMPは、コンストラクターの終わりではなく、Main()の終わりにスコープを通過します。しかし、これは悪い習慣です。メンバー変数は、インスタンスの外側に存在する変数への参照ではないようにしてください。実際には、その変数がいつ範囲外になるかはわかりません。
私がお勧めするのは、sandbox.memberをaとして定義することです const string member;
これにより、メンバー変数を一時パラメーター自体として割り当てる代わりに、一時パラメーターのデータをメンバー変数にコピーします。
技術的に言えば、このプログラムは実際に標準の出力に何かを出力する必要はありません(これは最初からバッファリングされたストリームです)。
cout << "The answer is: "
ビットは放出されます"The answer is: "
に バッファ stdoutの。そうして
<< sandbox.member
ビットはダングリングリファレンスをに提供しますoperator << (ostream &, const std::string &)
, 、それを呼び出します 未定義の動作.
このため、何も起こりません。プログラムは、一見うまく機能するか、stdoutをフラッシュすることなくクラッシュする可能性があります。テキストを意味します。「答えは次のとおりです。」画面に表示されません。
サンドボックスコンストラクターが戻ってから一時的な文字列がスコープから外れ、それによって占有されているスタックが他の目的のために回収されたためです。
一般的に、参照を長期にわたって保持しないでください。参照は、引数やローカル変数に適しています。クラスメンバーはありません。
あなたは姿を消したものに言及しています。以下が機能します
#include <string>
#include <iostream>
class Sandbox
{
public:
const string member = " "; //default to whatever is the requirement
Sandbox(const string& n) : member(n) {}//a copy is made
};
int main()
{
Sandbox sandbox(string("four"));
std::cout << "The answer is: " << sandbox.member << std::endl;
return 0;
}