A()= A() - 为什么要编译?

时间:2013-04-30 15:08:23

标签: c++

class A {};

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

为什么这段代码会编译?不应该有一些错误,在赋值运算符的左侧应该放置左值?是A()左值? g ++ 4.7版本

3 个答案:

答案 0 :(得分:87)

对于内置类型,你是对的:内置赋值运算符需要在左侧有一个可修改的左值

但是,这不是使用内置运算符,而是由类隐式声明的重载。这是一个成员函数,相当于

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

可以在 rvalues 上调用成员函数。

答案 1 :(得分: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; 
}

live example

请注意各种&表单声明结尾处的&&operator=(也称为引用限定符)。这使得分别为左值和右值选择这些声明。但是,rvalue版本在通过重载分辨率选择时会导致程序格式错误,因为它已被删除。

默认生成的operator =,但没有任何ref-qualifier,这意味着可以为lvalues和rvalues调用它;这就是问题中代码编译的原因,即使A()是一个右值。

答案 2 :(得分:1)

C ++编译器为所有类提供了一个默认构造函数,就你的代码而言,这就是你所说的代码。 A()= A(); 它只是使用无名对象调用构造函数,函数返回对构造对象的引用(隐式)。就是这样......