【问题标题】:Constructed temporary object are lvalue?构造的临时对象是左值吗?
【发布时间】:2014-10-13 04:15:42
【问题描述】:
假设我有一个名为 Foo 的类,它带有复制赋值运算符,我认为是这样的:
Foo() = Foo();
是不允许的,因为我认为(对不起,再次) Foo() 是一个右值(所以我不能分配给它),是一个临时对象。
显然,我试图让这段代码工作,它工作正常,显示一些字符串来验证我的程序是否正确使用了复制赋值运算符。
我错了吗?或者这是一种错误?能有什么用?
【问题讨论】:
标签:
c++
constructor
temporary
rvalue
【解决方案1】:
对象不能是“右值”或“左值”。不同类型的值(左值、右值、xvalue、prvalue等)的概念适用于表达式,用于访问对象,而不是对象本身。
在您的情况下,功能转换表达式Foo() 确实会产生一个临时对象作为右值。但是,在该临时对象的任何方法中,您都可以使用表达式*this,它会将相同的临时对象公开为左值。换句话说,临时对象是右值的流行观点显然是不正确的。使用哪种表达式访问对象始终是一个问题。
您可以在作业的左侧使用它,这并不奇怪。 “左值”要求仅适用于 内置 赋值运算符。对于 overloaded 赋值运算符,没有这样的要求,也从来没有。在您的情况下,您使用的是重载运算符。
【解决方案2】:
您说得对,= 运算符通常要求其左操作数是左值。但是,当运算符应用于已重载的类型时,它们将转换为函数调用。您的代码相当于:
Foo().operator=(Foo())
. 运算符很乐意接受右值作为其左操作数。
【解决方案3】:
Foo() 是一个右值,这是肯定的。
但是表达式Foo() = Foo() 等价于Foo().operator=(Foo())。即使Foo() 是一个右值,你仍然可以调用它的成员函数,甚至是修改它的成员函数。
当然,基本类型的右值不允许出现在赋值的左侧。在这方面,基本类型与用户定义类型的处理方式不同。
这就是为什么在 C++ 中,“左值”不应该被定义为“可以出现在赋值左侧的东西”!
【解决方案4】:
Foo 有一个重载的复制分配/移动分配运算符。要么是隐式提供的,要么是您自己编写的。无论哪种方式,因为Foo() 是一个实例,它能够像访问常规成员函数一样访问成员函数运算符。