21

左辺値とは

4

8 に答える 8

29

左辺値は、次のものに割り当てることができる値です。

lvalue = rvalue;

これは "left value" または "lefthand value" の略で、基本的には符号の左側の=、つまり何かを割り当てる値です。

左辺値ではないものの例(つまり、右辺値のみ):

printf("Hello, world!\n") = 100; // WTF?

printf()(を返す関数int) は左辺値にすることはできず、右辺値にすることはできないため、そのコードは機能しません。

于 2009-02-23T21:23:31.100 に答える
12

割り当ての左側に表示されるもの、つまり割り当て可能なもの。

C++ では、次の場合に関数呼び出しが左辺値になる可能性があることに注意してください。

int & func() {
   static int a = 0;
   return a;
}

それから:

func() = 42;     // is legal (and not uncommon)
于 2009-02-23T21:22:31.807 に答える
12

これは伝統的に "=" 演算子の左側です。ただし、時間の経過とともに、「左辺値」/「右辺値」の意味が変わりました。C++ では、代入できない左辺値である「変更不可能な左辺値」という用語が追加されました。「const」で修飾された配列と変数は 2 つの例です。C では、右辺値に割り当てることはできません (以下を参照)。同様に、C++ では、ユーザー定義のクラス型ではない右辺値に割り当てることはできません。

「左辺値」は、時間の経過とともに持続し、ストレージの特定の場所を占有するオブジェクトに名前を付ける式であると言えます。その式に割り当てることができるかどうかは、その分類にとって重要ではありません。特に、参照は、時間の経過とともに持続する名前を持つため、左辺値でもあります。以下はすべて、名前付きオブジェクトを参照するため、左辺値です。constまた、 aは左辺値性に影響を与えないことに注意してください。

int a; lvalue: a;
       lvalue: ++a;
int a[2]; lvalue: a;
int &ra = a; lvalue: ra;
int *pa = &a; lvalue: *pa;

「右辺値」という用語は、リテラルや列挙子の値など、および長寿命の楽しみを享受せず、完全な式の最後ですぐに破棄される一時的なものに使用されます。右辺値の場合、永続性の側面ではなく、値の側面が重要です。C++ の関数は、オブジェクトではありませんが、永続的でアドレスを持っているため、左辺値です。最初にオブジェクトのみを考慮した方が左辺値を把握しやすいため、上記の左辺値の概要ではそれらを省略しました。以下はすべて右辺値です。

enum { FOO, BAR }; rvalue: BAR;
int a[2]; rvalue: (a+1);
rvalue: 42;
int a; rvalue: a++; // refering to a temporary
struct mystruct { }; mystruct f() { return mystruct(); } rvalue: f();

ちなみに、多くの場合、左辺値がありますが、演算子には右辺値が必要です。たとえば、バイナリ組み込みの「+」演算子は 2 つの値を加算します。左辺値式は、最初に値を最初に読み取る必要がある場所を指定します。したがって、2 つの変数を追加すると、「左辺値から右辺値へ」の変換が行われます。標準では、左辺値式に含まれる値はその右辺値の結果であると述べています。

int a = 0, b = 1;
int c = a + b; // read values out of the lvalues of a and b. 

他の演算子は右辺値ではなく左辺値を取ります。彼らは値を読みません。例として、address-of 演算子があり&ます。右辺値式のアドレスを取得することはできません。一部の右辺値はオブジェクトでさえありません。それらはストレージを占有しません。例としては、リテラル (10、3.3、...) と列挙子の値があります。

その恐ろしいものはどのように役立ちますか?

左辺値と右辺値を区別することにはいくつかの利点があります

  • コンパイラが右辺値のストレージの取得とスカラー値のレジスタ/読み取り専用メモリの使用を省略できるようにする
  • とらえどころのない式としてフラグを立てる: 右辺値は長生きしません
    • コンパイラの効率的なコピー セマンティクスを内部的に許可し、c++1x ではプログラマーにも公開されます (ムーブ セマンティクスと右辺値参照を参照): とにかく破棄される右辺値からリソースを盗むことができます。
  • そのプロパティに基づいてルールを構築できます
    • 左辺値が参照する、まだ初期化されていないオブジェクトから右辺値を生成することはできません。しかし、左辺値は初期化されていないオブジェクトを問題なく参照できます
    • 右辺値は決して多態的ではありません。それらの静的型は動的型でもある必要があります: typeid 演算子の規則を簡素化します。

…それ以上のものがあります、私はそれを感じます…

于 2009-02-23T21:46:23.200 に答える
8

私が知っている最良の説明の 1 つは、RValue 参照に関するこの記事にあります

式が左辺値かどうかを判断する別の方法は、「そのアドレスを取得できますか?」と尋ねることです。可能であれば、それは左辺値です。できない場合は右辺値です。たとえば、 &obj 、 &*ptr 、 &ptr[index] 、 &++x はすべて有効ですが (これらの式のいくつかはばかげていますが)、 &1729 、 &(x + y) 、 &std::string("meow ") 、 &x++ はすべて無効です。なぜこれが機能するのですか?address-of 演算子では、その「オペランドは左辺値でなければならない」(C++03 5.3.1/2) 必要があります。なぜそれが必要なのですか?永続オブジェクトのアドレスを取得することは問題ありませんが、一時オブジェクトはすぐに蒸発するため、一時オブジェクトのアドレスを取得することは非常に危険です。

于 2009-02-23T21:33:52.403 に答える
2

左辺値の「L」は通常、「場所」を表すものとして記述されます。左辺値は何かの場所を指定します。別の回答者が指摘したように、左辺値は通常、アドレスを取得できます。これが、数値リテラルと非参照関数の戻り値が左辺値ではない理由です。

const が C++ に導入されるまで、L は「左」を表していました。const 左辺値は、代入の左側には表示できません。

于 2009-02-23T22:05:44.650 に答える
0

この記事から。OPは彼の質問をするのが少し怠惰だったので(同意しない人もいますが、コメントを参照してください)、私も怠け者になり、関連する部分全体をここに貼り付けるだけで、おそらくいくつかの著作権法に違反します.

オブジェクトは、調べて格納できるストレージの領域です。左辺値は、そのようなオブジェクトを参照する式です。左辺値は、それが指定するオブジェクトの変更を必ずしも許可するとは限りません。たとえば、const オブジェクトは変更できない左辺値です。変更可能な左辺値という用語は、左辺値によって、指定されたオブジェクトを変更および検査できることを強調するために使用されます。次のオブジェクト型は左辺値ですが、変更可能な左辺値ではありません:

  • 配列型
  • 不完全なタイプ
  • const 修飾された型
  • オブジェクトが構造体型または共用体型であり、そのメンバーの 1 つに const 修飾型がある

これらの左辺値は変更できないため、割り当てステートメントの左側には表示できません。

C++ では、参照を返す関数呼び出しは左辺値です。それ以外の場合、関数呼び出しは右辺値式です。C++ では、すべての式が左辺値または右辺値を生成するか、値を生成しません。

一部の演算子では、一部のオペランドに左辺値が必要です。次の表に、これらの演算子とその使用に関する追加の制約を示します。

     オペレーター要件
     & (単項) オペランドは左辺値でなければなりません。
     ++ -- オペランドは左辺値でなければなりません。
                                          これは両方のプレフィックスに適用されます
                                            および後置フォーム。
     = += -= *= %= >= &= ^= |= 左オペランドは左辺値でなければなりません。

たとえば、すべての代入演算子は、右側のオペランドを評価し、その値を左側のオペランドに割り当てます。左オペランドは、変更可能な左辺値または変更可能なオブジェクトへの参照でなければなりません。

アドレス演算子 (&) にはオペランドとして左辺値が必要ですが、インクリメント (++) およびデクリメント (--) 演算子にはオペランドとして変更可能な左辺値が必要です。

于 2009-02-23T21:25:07.167 に答える
0

左辺値ではないことの簡単な例:

3 = 42;
于 2009-02-23T21:49:23.677 に答える