赋值给右值:为什么这样编译可以通过?

6
在下面的示例中:
class A {
  private: double content;

  public:
  A():content(0) {}

  A operator+(const A& other) {     
    content += other.content;
    return *this;
  }

 void operator=(const A& other) {
       content = other.content;
  }

};

A是一个简单的双精度浮点数包装器,其中+=运算符已被重载。在下面的使用中:

 int main(int argc, char *argv[]) {
    A a, b, c;
    (a+b) = c ; // Why is this operation legal?
}

为什么(a+b) = c可以编译通过?我想知道为什么这个语句是合法的,因为(a+b)的结果必须是一个rvalue。我没有从operator+返回一个引用。


2
重载运算符只是函数调用,它们对参数的值类别没有任何特殊限制。由于您没有为赋值运算符重载指定引用资格限定符,因此它接受任何值类别的实例。 - Kerrek SB
请问您能否详细说明一下? - ForeverStudent
1
好吧,你不会抱怨(a + b).display()能正常工作,对吧? - Kerrek SB
1个回答

14

(a+b) = c(a+b).operator=(c)是一样的。在赋值运算符中,对于右值引用没有特殊规定,它只遵循普通函数调用的规则。如果你想防止使用右值调用,可以添加一个ref-qualifier:

(a+b) = c(a+b).operator=(c)是相同的。在赋值操作符中,没有特殊的规则适用于右值引用,它只需遵循通常的函数调用规则。如果你想防止使用rvalue进行调用,可以添加一个ref-qualifier:

void operator= (const A& other) & {
//                              ^
     content = other.content;
}

这将仅允许在lvalue上调用该函数。


因此,通常情况下,由于默认的赋值运算符要求左侧具有 lvalue(除了 C++11 的右值引用),但当我自己重载 = 运算符时,这个要求就不再适用了,是吗? - ForeverStudent
@IIIIIIIIIIIIIIIIIIIIIIII 是的。 - TartanLlama
1
@TartanLlama 不是的,实际上;对于类类型来说,默认的 operator= 也允许左侧是 prvalue。无论是否有用户提供的重载都没有影响。你显然是在指左侧有一个原始类型(不确定 OP 是否也清楚)。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接