214

最初に参照を返すのはなぜですか?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;

2番目はそうではありませんが?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

実際、2番目はまったくコンパイルされませんでした-「代入の左辺値ではありません」。

4

3 に答える 3

177

式には戻り値の型がなく、型と (最新の C++ 標準で知られているように) 値カテゴリがあります。

条件式は、左辺値または右辺値にすることができます。これはその値のカテゴリです。(これは、C++11左辺値、x 値、および prvalues があるため、多少単純化されています。)

非常に広く簡単に言えば、左辺値はメモリ内のオブジェクトを指し、右辺値はメモリ内のオブジェクトに必ずしも関連付けられていない値にすぎません。

代入式はオブジェクトに値を代入するため、代入先は左辺値でなければなりません。

条件式 ( ?:) が左辺値(広義で簡単な用語で言えば) であるためには、2 番目と 3 番目のオペランドは同じ型の左辺値でなければなりません。これは、条件式の型と値のカテゴリがコンパイル時に決定され、条件が真かどうかに関係なく適切でなければならないためです。オペランドの 1 つを別の型に変換して他の型と一致させる必要がある場合、この変換の結果は左辺値にならないため、条件式を左辺値にすることはできません。

ISO/IEC 14882:2011 の参照:

3.10 [basic.lval] 左辺値と右辺値 (値カテゴリについて)

5.15 [expr.cond] 条件演算子 (条件式が持つ型と値のカテゴリに関する規則)

5.17 [expr.ass]代入および複合代入演算子 (代入の左辺が変更可能な左辺値でなければならないという要件)

于 2011-12-16T14:05:08.010 に答える
60

三項?:式の型は、2 番目と 3 番目の引数の共通の型です。両方の型が同じ場合は、参照が返されます。それらが相互に変換可能な場合、一方が選択され、もう一方が変換されます (この場合は昇格)。一時変数 (変換された変数または昇格された変数) への左辺値参照を返すことはできないため、その型は値型です。

于 2011-12-16T13:59:32.290 に答える
19

の型と一致するようにの型を暗黙的にプロモートする必要があるため( の両側が同じ型ではないため)、左辺値を返すことはできず、一時的なものを作成する必要があります。xy:


基準は何と言っていますか?( n1905 )

式 5.17 代入演算子と複合代入演算子

5.17/3

2 番目と 3 番目のオペランドの型が異なり、どちらかが (おそらく cv 修飾された) クラス型である場合、これらのオペランドのそれぞれを他方の型に変換する試みが行われます。タイプ T1 のオペランド式 E1 がタイプ T2 のオペランド式 E2 と一致するように変換できるかどうかを判別するプロセスは、次のように定義されます。

— E2 が左辺値の場合: E1 を暗黙的に「T2 への参照」型に変換できる場合 (第 4 節)、E1 は E2 に一致するように変換できますが、変換では参照が直接バインドしなければならないという制約 (8.5.3 ) E1 へ。

— E2 が右辺値の場合、または上記の変換を実行できない場合:

— E1 と E2 がクラス型を持ち、基礎となるクラス型が同じであるか、一方が他方の基本クラスである場合: T2 のクラスが E2 と同じ型であるか、またはその基本クラスである場合、E1 は E2 に一致するように変換できます。 、T1 のクラス、および T2 の cv-qualification は、T1 の cv-qualification と同じ cv-qualification、またはそれより大きい cv-qualification です。変換が適用されると、E1 は、元のソース クラス オブジェクト (またはその適切なサブオブジェクト) を引き続き参照する T2 型の右辺値に変更されます。[注: つまり、コピーは作成されません。— 終了注] E1 から T2 型のテンポラリをコピー初期化し、そのテンポラリを変換されたオペランドとして使用します。

それ以外の場合 (つまり、E1または E2 に非クラス型がある場合、または両方にクラス型があるが、基になるクラスが同じでないか、一方が他方の基本クラスでない場合): E1 が E1 E2 が右辺値に変換された場合に式 E2 が持つ型 (または E2 が右辺値の場合はその型) に暗黙的に変換されます。

このプロセスを使用して、第 2 オペランドが第 3 オペランドと一致するように変換できるかどうか、および第 3 オペランドが第 2 オペランドと一致するように変換できるかどうかが判断されます。両方を変換できる場合、または一方を変換できても変換があいまいな場合、プログラムは不正な形式です。どちらも変換できない場合、オペランドは変更されずに残され、以下で説明するようにさらにチェックが実行されます。変換が 1 つだけ可能である場合、その変換は選択されたオペランドに適用され、変換されたオペランドは、このセクションの残りの部分で元のオペランドの代わりに使用されます。


5.17/4

2 番目と 3 番目のオペランドが左辺値で同じ型の場合、結果はその型で左辺値になり、2 番目または 3 番目のオペランドがビット フィールドの場合、または両方がビット フィールドの場合はビット フィールドになります。田畑。


5.17/5

それ以外の場合、結果は右辺値です。2 番目と 3 番目のオペランドが同じ型を持たず、どちらかが (おそらく cv 修飾された) クラス型を持っている場合、オペランドに適用される変換 (存在する場合) を決定するためにオーバーロードの解決が使用されます (13.3.1.2、13.6)。 . オーバーロードの解決に失敗した場合、プログラムは不適切な形式です。それ以外の場合は、このように決定された変換が適用され、変換されたオペランドが、このセクションの残りの部分で元のオペランドの代わりに使用されます。

于 2011-12-16T14:00:46.393 に答える