A()= A()-なぜコンパイルするのですか?


85
class A {};

int main() {
 A() = A();
 return 0; 
}

このコードがコンパイルされるのはなぜですか?代入演算子の左側に左辺値を配置する必要があるというエラーはありませんか?A()は左辺値ですか?g ++ 4.7バージョン

回答:


88

組み込み型の場合は正しいでしょう。組み込み代入演算子には、左側に変更可能な左辺値が必要です。

ただし、これは組み込み演算子を使用していませんが、クラスによって暗黙的に宣言されているオーバーロードを使用しています。これはメンバー関数であり、同等です

A().operator=(A());

メンバー関数は右辺値で呼び出すことができます。


7
コピーの初期化ではありませんか?
スターダスト2013

13
@Named:いいえ、初期化ではなく割り当てです。
Mike Seymour

1
@ paul23:それは本当です(あなたがそうではoperator=ないと仮定してoperator())、しかし質問とはあまり関係がありません。この例では、割り当ての結果には何もしません。
Mike Seymour

3
@ paul23A()はを呼び出さずoperator()、型のオブジェクトを作成しますA
interjay 2013

3
宣言がないため、初期化することはできません。
コス2013

32

本当に必要な場合は、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()は右辺値であってもコンパイルされます。


1

C ++コンパイラーは、すべてのクラスにデフォルトのコンストラクターを提供します。これは、A()= A()と言うと、コードに関して発生します。名前のないオブジェクトを使用してコンストラクターを呼び出すだけで、関数は構築されたオブジェクトへの参照を返します(暗黙的)。それでおしまい...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.