右辺値、左辺値、POD、および非 POD に関して詳細を説明できる人はいますか? 私の理解では、int() と A() の両方が右辺値である必要があります。
struct A {};
int main()
{
int i;
A a;
int() = i; //Not OK (error).
A() = a; //OK.
return 0;
}
右辺値は、式から得られるものです (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() = 1
int には operator= が同じように実装されていないため、発見したように明示的に禁止されています。ただし、このタイプ間のわずかな不一致は、実際には問題になりません (少なくとも私が発見したことはありません)。
POD は Plain Old Data を意味し、memcpy を使用することがコピーに相当することを指定する要件の集まりです。非 POD は、memcpy を使用してコピーできない型です (POD の自然な反対で、ここには何も隠されていません)。これは、C++ で作成するほとんどの型になる傾向があります。POD であろうと非 POD であろうと、上記のいずれも変わらず、実際には別の問題です。
私の理解では、int() と A() の両方が右辺値である必要があります。
正解です。epxresessionT()
は常にスカラーおよびユーザー定義型の右辺値ですT
。no が含まれている限り、より正確に言えばconst
、式T()
は変更可能な rvalueです。
スカラー型を含む代入では、代入演算子の左側に変更可能な左辺値が必要です。は左辺値ではないためint()
、に代入できませんint()
。
ユーザー定義型の場合、割り当ては特別なメンバー関数であり、メンバー関数は右辺値でも呼び出すことができます( §3.10セクション 10 を参照)。そのため、A().operator=(a)
形が整っています。
From C++ は POD typedef の値の初期化を行いますか? 、これは標準を引用しています:
式 T() (T は非配列完全オブジェクト型または (おそらく cv 修飾された) void 型の単純型指定子 (7.1.5.2)) であり、指定された型の右辺値 (値) を作成します。 -初期化済み
したがって、最初のケースで見たように、 int() は右辺値であり、割り当てることはできません。
A() は単純型指定子ではないため、A() は左辺値を生成します