class A {};
int main() {
A() = A();
return 0;
}
このコードがコンパイルされるのはなぜですか?代入演算子の左側に左辺値を配置する必要があるというエラーはありませんか?A()は左辺値ですか?g ++ 4.7バージョン
回答:
組み込み型の場合は正しいでしょう。組み込み代入演算子には、左側に変更可能な左辺値が必要です。
ただし、これは組み込み演算子を使用していませんが、クラスによって暗黙的に宣言されているオーバーロードを使用しています。これはメンバー関数であり、同等です
A().operator=(A());
メンバー関数は右辺値で呼び出すことができます。
operator=ないと仮定してoperator())、しかし質問とはあまり関係がありません。この例では、割り当ての結果には何もしません。
A()はを呼び出さずoperator()、型のオブジェクトを作成しますA。
本当に必要な場合は、C ++ 11でコンパイルしないようにすることができます。
class A {
template <typename T>
void operator=(T&&) && = delete; // no op= for rvalues
// generate other special members normally
A() = default;
A(A const&) = default;
A(A&&) = default;
~A() = default;
// op= only for lvalues
A& operator=(A&&) & = default;
A& operator=(A const&) & = default;
};
int main() {
A() = A(); // error
return 0;
}
(実例)
さまざまな形式の宣言の最後にある&and &&(別名ref-qualifiers)に注意してくださいoperator=。これにより、これらの宣言が左辺値と右辺値に対してそれぞれ選択されます。ただし、右辺値バージョンを過負荷解決で選択すると、プログラムが削除されるため、プログラムの形式が正しくなくなります。
ただし、デフォルトで生成されたoperator =にはref修飾子がありません。つまり、左辺値と右辺値の両方に対して呼び出すことができます。そのため、質問のコードA()は右辺値であってもコンパイルされます。
C ++コンパイラーは、すべてのクラスにデフォルトのコンストラクターを提供します。これは、A()= A()と言うと、コードに関して発生します。名前のないオブジェクトを使用してコンストラクターを呼び出すだけで、関数は構築されたオブジェクトへの参照を返します(暗黙的)。それでおしまい...