需要一些关于r值概念的帮助

Need some help on r-value concept

本文关键字:帮助      更新时间:2023-10-16

当我尝试编译以下程序时,我在l-value上得到了一个错误,这是有道理的。错误为:错误C2106:"=":左操作数必须是l-value

代码:

int main() 
{
    int a,b,c,d;
    b+c=d;
    return 0;
 }

但当我用自己的结构替换integer时,下面的代码绝对有效

struct MyStruct
{
    int val;
    MyStruct(){}
};
MyStruct operator+(MyStruct& s1, MyStruct& s2)
{
    MyStruct temp;
    return temp;
}
int main() 
{
    MyStruct a,b,c,d;
    b+c=d;
    return 0;
}

第二个代码是如何编译的?我知道我可以从运算符+返回const。但第二个例子中的b+c不是一个右值吗?那么它是如何编译的呢

Cory Klein已经在这里解释了代码编译的原因。

我只想补充一点,如果您希望MyStruct表现为ints(以及其他内置类型),那么将此行添加到MyStruct:

MyStruct& operator =(const MyStruct&) && = delete;

这告诉编译器,每次对作为右值的MyStruct对象调用operator =()时(由于ref-限定符&&),代码都应该无效,因为operator =()不存在(= delete;)。事实上,GCC 4.8.1包含以下内容:

错误:使用已删除的函数"MyStruct&MyStruct::运算符=(const MyStruct&)&'

b+c=d;
   ^

更新:关注Casey的评论(非常感谢)。

将上面的行添加到MyStruct中有一个问题。它还防止赋值给左值。也就是说,下面的行也变成了非法的:

b = c;

如果您想禁用对左值的赋值,但仍然允许对左值进行赋值,那么将该行添加到MyStruct:中,而不是上面的行

MyStruct& operator =(const MyStruct&) & = default;

(或者,如果编译器生成的实现不符合您的目的,则提供正确的实现。)

在此代码中:

MyStruct a,b,c,d;
b+c=d;

正如您定义的operator+()函数一样,它返回一个MyStruct。因此,调用您定义的函数的b+c返回一个MyStruct,然后在该MyStruct上调用operator=()函数,并将其作为参数传递给d

尽管临时MyStruct是一个右值,因为它是临时性的,但由于我上面解释的原因,以及当右值是用户定义的对象而不是积分类型时,C++标准不禁止在该右值上调用operator=()函数,代码仍然可以编译。

在此代码中:

int a,b,c,d;
b+c=d;

b+c返回一个r值int。在=运算符的左侧具有r值不是C++语法。无论哪种方式,为其赋值都没有任何意义,而在临时MyStruct上调用operator=()函数可能会产生副作用。