C++ での参照の初期化
-
19-09-2019 - |
質問
みなさん、こんにちは!
自分のコードを調べてみると、次のような興味深い行にたどり着きました。
const CString &refStr = ( CheckCondition() ) ? _T("foo") : _T("bar");
今私は完全に途方に暮れており、なぜそれが合法なのか理解できません。私が理解している限り、const 参照は r 値または l 値で初期化する必要があります。初期化されていない参照は存在できません。しかし ()?演算子は、参照に値を割り当てる前に CheckCondition() 関数を実行します。CheckCondition() の実行中、refStr は存在しますが、まだ初期化されていないことがわかります。CheckCondition() が例外をスローする場合、または goto ステートメントで制御を渡す場合はどうなりますか?参照が初期化されないままになりますか、それとも何かが足りないのでしょうか?
解決
よりシンプルな例:const int x = foo();
この定数はあまりにも初期化されなければならない、そしてそのfoo()
のために呼び出す必要があります。それは、必要な順序で行われます。xはexistanceに入ってくるときにだけfooの戻り
あなたの追加の質問に答えるために:foo()
がthrow
希望の場合、例外がどこかcatch()
によって捕捉されます。そのtry{}
ためcatch()
ブロックは明らかにconst int x = foo();
を取り囲みました。したがってconst int x
すでにスコープ外であり、それは価値をやったことがなかったということは関係ありません。例外のためのcatch
がない場合や、(const int x
含む)あなたのプログラムがなくなっています。
C ++は、ランダムgoto
年代を持っていません。彼らはfoo()
以内にジャンプすることができますが、それは問題ではありません。 foo()
はまだ返すために持っています。
他のヒント
あなたは何かが欠けている - それは完全に法律上のコードであり、実際にそのようなコードは、条件演算子の最も一般的な、最高の用途の一つです。これは、コードがページ上にレイアウトされていることと同じ順序でコンパイラが内部的に物事を行う必要があることを考えるのは常に間違いだ - それは(justv別の表現である)条件演算子を評価し、その後に結果を使用するように自由に完璧です初期化を実行します。
ジャンプについては、初期化の一方を使用する方法はありません。例外がスローされた場合や、参照が最初の場所で作成されていないために決してみなされます。
初期化されていない参照は存在できません。
残念ながら、初期化中におかしなことが起こる可能性があります。と書くこともできたでしょう
const int& a = foobar(a) ? 1 : 2;
あるいはついでに言えば
const int& a = a;
コンパイラが左から右に進むと、確かに a は右側のスコープ内にあると思います。 技術的に 使用できるはずで、せいぜい警告が表示される程度です。
「ComeauTest.c」、9行目:警告:変数「a」は値が設定される前に使用されます
const int& a = foobar(a) ? 1 : 2;
^
当然のことながら、初期化されていない変数を使用した場合と同様に、未定義の動作が発生するだけです。
初期化される前に参照を使用しないため、あなたの例は問題ありません。
CheckCondition() の実行中、refStr は存在しますが、まだ初期化されていないことがわかります。
言語弁護士の観点からすると、これは間違っています。初期化中に、 refStr
まだ存在しません。ビジュアル デバッガーが誤解を招くヒントを提供しているのではないかと思います。
初期化内のコードがエラー状態を引き起こす場合、 refStr
存在しないし、これからも存在しないでしょう。
これは完全に合法です。このいずれかが正常に終了しないと参照が有効なオブジェクトにバインドされているか、例外がスローされ、制御はブロック外に転送され、誰もがもうそれで気に基準がスコープ内にもはやます。
例外はrefStrにアクセスできない場所にあなたをもたらすでしょう、あなたはそれがあるからである場所に行くことができません。後藤はCheckCondition()は関数の場合から抜け出すことができなくなり、それがマクロである場合は、goto文を使用することはできません。 longjmp関数は、()は例外と同じ効果を持ちます:あなたはrefStrにアクセスできない場所に行くよ。