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


85
class A {};

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

为什么要编译此代码?应该不会在赋值运算符的左侧放置左值吗?是A()左值吗?g ++ 4.7版本

Answers:


88

对于内置类型,您将是正确的:内置赋值运算符在左侧需要可修改的左值

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

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

成员函数可以在rvalues调用


7
它不是复制初始化吗?
stardust

13
@Named:不,它的分配没有初始化。
Mike Seymour 2013年

1
@ paul23:的确是这样(假设您的意思operator=不是operator()),但与问题无关。该示例对分配的结果不做任何事情。
Mike Seymour

3
@ paul23A()不调用operator(),它构造一个类型的对象A
interjay 2013年

3
不能初始化,因为没有声明。
科斯

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; 
}

现场示例

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

但是,默认生成的operator =没有任何ref限定符,这意味着它可以同时用于左值和右值。这就是为什么即使A()是右值也可以编译问题中的代码的原因。


1

C ++编译器为所有类提供一个默认构造函数,这就是您说代码A()= A()时发生的事情。它只是使用无名对象调用构造函数,并且该函数返回对构造对象的引用(隐式)。而已...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.