22

右辺値、左辺値、POD、および非 POD に関して詳細を説明できる人はますか? 私の理解では、int() と A() の両方が右辺値である必要があります。


struct A {};

int main()
{
  int i;
  A a;

  int() = i; //Not OK (error).
  A() = a; //OK.

  return 0;
}

4

3 に答える 3

19

右辺値は、式から得られるものです (C 標準から取った便利な簡略化ですが、C++ 標準では表現されていません)。左辺値は「ロケーター値」です。左辺値は右辺値として使用できます。const であっても、参照は常に左辺値です。

知っておかなければならない主な違いは、1 つの項目に要約できます: 右辺値のアドレスを取得することはできません (これも、標準ではなく、ルールの有用な一般化です)。別の言い方をすれば、右辺値の正確な位置を修正することはできませ。(ただし、const& を右辺値にバインドして「その場で修正」することはできます。0x はルールを大幅に変更しています。)

ただし、ユーザー定義型 (UDT) は少し特殊です。クラスのインターフェイスで許可されている場合は、任意の右辺値を左辺値に変換できます。

struct Special {
  Special& get_lvalue() { return *this; }
};
void f() {
  // remember "Special()" is an rvalue
  Special* p = &Special().get_lvalue(); // even though you can't dereference the
  // pointer (because the object is destroyed), you still just took the address
  // of a temporary

  // note that the get_lvalue() method doesn't need to operate on a const
  // object (though that would be fine too, if the return type matched)
}

右辺値を に変換A() = aするために、コンパイラが提供する代入演算子を除いて、あなたの に対して同様のことが起こっています。標準 12.8/10 を引用すると、次のようになります。A()*this

クラス定義でコピー代入演算子が明示的に宣言されていない場合は、暗黙的に宣言されます。クラス X の暗黙的に宣言されたコピー代入演算子は、次の形式になります。

X& X::operator=(const X&)

そして、さらに多くの資格と仕様が続きますが、それがここで重要な部分です. これはメンバー関数であるため、Special::get_lvalue と同じように、右辺値で呼び出すことができA().operator=(a)ますA() = a

int() = 1int には operator= が同じように実装されていないため、発見したように明示的に禁止されています。ただし、このタイプ間のわずかな不一致は、実際には問題になりません (少なくとも私が発見したことはありません)。


POD は Plain Old Data を意味し、memcpy を使用することがコピーに相当することを指定する要件の集まりです。非 POD は、memcpy を使用してコピーできない型です (POD の自然な反対で、ここには何も隠されていません)。これは、C++ で作成するほとんどの型になる傾向があります。POD であろうと非 POD であろうと、上記のいずれも変わらず、実際には別の問題です。

于 2010-02-19T03:43:03.883 に答える
2

私の理解では、int() と A() の両方が右辺値である必要があります。

正解です。epxresessionT()は常にスカラーおよびユーザー定義型の右辺値ですT。no が含まれている限り、より正確に言えばconst、式T()変更可能な rvalueです。

スカラー型を含む代入では、代入演算子の左側に変更可能な左辺値が必要です。は左辺値ではないためint()、に代入できませんint()

ユーザー定義型の場合、割り当ては特別なメンバー関数であり、メンバー関数は右辺値でも呼び出すことができます( §3.10セクション 10 を参照)。そのため、A().operator=(a)形が整っています。

于 2010-02-19T10:26:30.737 に答える
1

From C++ は POD typedef の値の初期化を行いますか? 、これは標準を引用しています:

式 T() (T は非配列完全オブジェクト型または (おそらく cv 修飾された) void 型の単純型指定子 (7.1.5.2)) であり、指定された型の右辺値 (値) を作成します。 -初期化済み

したがって、最初のケースで見たように、 int() は右辺値であり、割り当てることはできません。

A() は単純型指定子ではないため、A() は左辺値を生成します

于 2010-02-19T03:26:25.480 に答える