web-dev-qa-db-ja.com

エラー:タイプ「int」の右辺値からのタイプ「int&」の非const参照の無効な初期化

間違った形式:

int &z = 12;

正しい形式:

int y;
int &r = y;

質問
最初のコードが間違っているのはなぜですか?タイトルのエラーの「meaning」とは何ですか?

77
Aquarius_Girl

C++ 03 3.10/1は、「すべての式は左辺値または右辺値です」と述べています。左辺値と右辺値は、オブジェクトではなく式のプロパティであることを覚えておくことが重要です。

左辺値は、単一の式を超えて持続するオブジェクトに名前を付けます。たとえば、obj*ptrptr[index]、および++xはすべて左辺値です。

右辺値は、それらが存在する完全な表現の終わりに(「セミコロンで」)蒸発する一時的なものです。たとえば、1729x + ystd::string("meow")、およびx++はすべて右辺値です。

アドレス演算子は、その「オペランドは左辺値」でなければなりません。 1つの式のアドレスを取得できる場合、その式は左辺値であり、それ以外の場合は右辺値です。

 &obj; //  valid
 &12;  //invalid
119
BruceAdi
int &z = 12;

右側では、タイプintの一時オブジェクトが整数リテラル12から作成されますが、一時は非const参照にバインドできません。したがって、エラー。以下と同じです:

int &z = int(12); //still same error

なぜ一時が作成されるのですか?参照はメモリ内のオブジェクトを参照する必要があり、オブジェクトが存在するためには、最初に作成する必要があります。オブジェクトには名前が付けられていないため、temporaryオブジェクトです。名前はありません。この説明から、2番目のケースがうまくいく理由が明らかになりました。

一時オブジェクトはconst参照にバインドできます。つまり、次のことができます。

const int &z = 12; //ok

C++ 11および右辺値リファレンス:

完全を期すために、C++ 11が一時オブジェクトにバインドできる右辺値参照を導入したことを追加したいと思います。したがって、C++ 11では、次のように記述できます。

int && z = 12; //C+11 only 

&&の代わりに&があることに注意してください。また、constがバインドするオブジェクトが、整数リテラル12から作成された一時オブジェクトであっても、zはもう必要ないことに注意してください。

C++ 11ではrvalue-referenceが導入されているため、int&は今後lvalue-referenceと呼ばれます。

46
Nawaz

12は、int&によって参照されるデータとは異なり、変更できないコンパイル時定数です。 canすることは

const int& z = 12;

非constおよびconst参照バインディングは異なる規則に従います

C++言語の規則は次のとおりです。

  • リテラル番号(12)で構成される式は「右辺値」です
  • 右辺値を持つ非const参照を作成することは許可されていません:int &ri = 12;は不正な形式です
  • 右辺値を持つconst参照を作成することが許可されています。この場合、名前のないオブジェクトがコンパイラによって作成されます。このオブジェクトは、参照自体が存在する限り存続します。

これらはC++のルールであることを理解する必要があります。彼らはただです。

わずかに異なるルールを使用して、C++などの別の言語を簡単に作成できます。 C++ 'では、右辺値を持つ非const参照を作成できます。ここには矛盾や不可能はありません。

しかし、プログラマーが意図したものを取得できない可能性のある危険なコードを許可し、C++デザイナーはそのリスクを回避することを当然決定しました。

4
curiousguy

参照は、変更可能なもの(左辺値)への「隠されたポインター」(非ヌル)です。それらを定数に定義することはできません。それは「可変」なものでなければなりません。

編集::

私は考えています

int &x = y;

とほぼ同等

int* __px = &y;
#define x (*__px)

ここで、__pxは新しい名前であり、#define xx参照の宣言を含むブロック内でのみ機能します。