请注意原问题标题中为“代替rvalue”而非“代替const引用”。下面的一个答案是针对旧标题而给出的。这已经被修复以提高清晰度。
C和C++中的一种常见结构是链式赋值,例如:
int j, k;
j = k = 1;
第二个
=
先执行,表达式 k=1
的副作用是将 k
设置为 1,而表达式本身的值是 1。然而,在 C++ 中合法但不在 C 中的一种构造是以下形式,适用于所有基本类型:
int j, k=2;
(j=k) = 1;
在这里,表达式
j=k
的副作用是将j
设置为2,而表达式本身变为对j
的引用,然后将j
设置为1。据我所知,这是因为表达式j=k
返回一个非-const
int&
,通常是左值。通常也建议为用户定义的类型使用此约定,如《Effective C++》中的“第10项:使赋值运算符返回(非const)引用*this”,其中我的括号补充说明。该书的这一部分并没有尝试解释为什么引用是非
const
的,甚至没有在经过之前注意到非const
。当然,这确实增加了功能,但语句
(j=k) = 1;
至少似乎有些尴尬。如果约定改为内置赋值返回const引用,则自定义类也将使用此约定,并且C中允许的原始链式构造仍将正常工作,而无需任何多余的复制或移动。例如,以下内容可以正确运行:
#include <iostream>
using std::cout;
struct X{
int k;
X(int k): k(k){}
const X& operator=(const X& x){
// the first const goes against convention
k = x.k;
return *this;
}
};
int main(){
X x(1), y(2), z(3);
x = y = z;
cout << x.k << '\n'; // prints 3
}
优点是所有3种类型(C内置、C++内置和C++自定义类型)都具有一致性,不允许出现像(j=k) = 1
这样的习惯用法。
在C和C++之间增加这种习惯用法是否是有意为之?如果是,什么情况下会使用它呢?换句话说,这种扩展功能提供了什么非虚假的好处呢?