在 r 值概念上需要一些帮助
Posted
技术标签:
【中文标题】在 r 值概念上需要一些帮助【英文标题】:Need some help on r-value concept 【发布时间】:2013-07-19 18:13:15 【问题描述】:当我尝试编译以下程序时,我得到一个有意义的左值错误。 错误是:错误 C2106:'=':左操作数必须是左值
代码:
int main()
int a,b,c,d;
b+c=d;
return 0;
但是当我用我自己的结构替换整数时,下面的代码工作得很好
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;
第二个代码是怎么编译的? 我知道我可以从 operator+ 返回 const。但是第二个例子中的 b+c 不是右值吗?那它是怎么编译的
【问题讨论】:
【参考方案1】:Cory Klein 已经解释了here 代码编译的原因。
我只想补充一点,如果你想让MyStruct
表现得像int
s(和其他内置类型),那么将此行添加到MyStruct
:
MyStruct& operator =(const MyStruct&) && = delete;
这告诉编译器每次在作为右值的MyStruct
对象上调用operator =()
时(感谢ref-qualifier &&
),代码应该是无效的因为operator =()
不存在(= delete;
)。事实上,GCC 4.8.1 发出了以下内容:
错误:使用已删除的函数 'MyStruct& MyStruct::operator=(const MyStruct&) &&'
b+c=d; ^
更新:关注Casey 的评论(非常感谢)。
将上面的行添加到MyStruct
存在一个问题。它还可以防止分配给左值。也就是说,下面这行也变成了非法的:
b = c;
如果您想禁用对右值的赋值但仍允许对左值进行赋值,则将上面的行添加到MyStruct
:
MyStruct& operator =(const MyStruct&) & = default;
(或者如果编译器生成的实现不符合您的目的,则提供正确的实现。)
【讨论】:
我一直在使用MyStruct& operator = (const MyStruct&) & = default;
来达到同样的目的。你能想到有什么理由支持删除而不是默认吗?
@Casey:我不知道这会做同样的事情。实际上,您的解决方案优于我的解决方案,我会更新我的答案。谢谢你。【参考方案2】:
在这段代码中:
MyStruct a,b,c,d;
b+c=d;
当您定义了operator+()
函数时,它返回一个MyStruct
。因此,调用您定义的函数的b+c
返回一个MyStruct
,然后在该MyStruct
上调用operator=()
函数,并将d
作为参数传递。
虽然是临时的MyStruct
is an rvalue,因为它的临时性质,但由于我上面解释的原因,代码仍然可以编译,而且C++标准并没有禁止在右值上调用operator=()
函数。该右值是用户定义的对象,而不是整数类型。
在这段代码中:
int a,b,c,d;
b+c=d;
b+c
返回一个 r 值 int。在 =
运算符的左侧有一个 r 值不是 C++ 语法。无论哪种方式,为其赋值都没有任何意义,而在临时 MyStruct
上调用 operator=()
函数可能会产生副作用。
【讨论】:
如果不是C++语法,那怎么编译?相反,如果我写 (b+c).val = d.val 这个失败 它不编译,你自己说 - 它得到错误代码 C2106。MyStruct
代码是正确的 C++ 语法,因此它可以编译。
感谢您的澄清。我想我的基本查询是为什么临时 Mystruct 不是 r 值
@Cory Klein:“那个临时的 MyStruct 不是 r 值。”。实际上,临时值是一个右值。问题是类类型的右值的行为不像内置类型的右值(正如您已经清楚解释的那样)。
我已经更新了答案,解释了为什么 MyStruct
不是右值。以上是关于在 r 值概念上需要一些帮助的主要内容,如果未能解决你的问题,请参考以下文章