++a
は左辺値ですが、a++
ではありません。これは、C++ 14 [expr.pre.incr]/1で指定される:
プレフィックス++
のオペランドは、1を加えることによって修飾されている[...] オペランドは変更左辺値でなければなりません。 [...]結果は更新されたオペランドです。それは左辺値
で、[expr.post.incr]/1:
[...]結果はprvalueです。
今、私たちはauto && b = ++a;
を考えます。 ++a
は左辺値です。 auto&&
は転送参照です。転送参照は実際にはlvaluesにバインドできます。auto
自体が参照型に推定される可能性があります。このコードはint &b = ++a;
と推測しています。
参照が同じ型の左辺値にバインドされている場合、参照が直接バインドされるため、b
はa
の別の名前になります。
第2の例では
、auto && b = a++;
、a++
prvalueあります。つまり、関連付けられたアドレスがなく、変数a
との関係はなくなりました。この行は、++a; auto && b = (a + 0);
と同じ動作をします。
まず、a++
は正価であるため、auto&&
はint&&
になります。 (すなわちauto
はint
になります)。非クラス型の参照がprvalueにバインドされると、一時オブジェクトは値からコピー初期化されます。このオブジェクトは、参照と一致するように拡張された存続期間を持ちます。第2のケースでそうb
がa
から別のオブジェクトにバインドされ、(それは限りb
がするように持続するので、本当に一時的ではありません)「一時的」int型。
参照バインディングルールは[dcl.init.ref]にあります。
私はあなたにヒントを与えます - 'a'はrvalueではありません。 – erip
@eripはい、私は知っていますが、 'b'の2つの例の違いは何ですか? – vladon
2番目の例では、 'b'は、最初の例のように、前にインクリメントせずに' a'の値を取得します。 – x13