假设我有一个名为Foo的类,带有复制赋值运算符,我认为这是:
Foo() = Foo();
是不允许的,因为我想(抱歉,再次)Foo()是一个右值(所以我不能分配给它),是一个临时对象。 显然,我试图使这段代码工作,并且它正常工作,显示一些字符串以验证我的程序正确使用了复制赋值运算符。
我错了吗?或者这是一种错误?有什么用处?
答案 0 :(得分:8)
Foo()
是左值,这是肯定的。
但表达式Foo() = Foo()
相当于Foo().operator=(Foo())
。即使Foo()
是一个右值,你仍然可以在它上面调用一个成员函数,甚至是一个修改它的成员函数。
当然,在作业的左侧不允许使用基本类型的右值。在这方面,基本类型的处理方式与用户定义的类型不同。
这就是为什么,在C ++中," lvalue"不应被定义为"可以出现在作业左侧的东西"!
答案 1 :(得分:1)
Foo
有一个重载的复制赋值/移动赋值运算符。可以隐式提供任何一个,也可以自己编写。无论哪种方式,因为Foo()
是一个实例,它能够像常规成员函数一样访问成员函数运算符。
答案 2 :(得分:1)
你是对的,=
运算符通常要求其左操作数是左值。但是,当运算符应用于已经重载的类型时,它们将转换为函数调用。您的代码相当于:
Foo().operator=(Foo())
.
运算符会很乐意接受右值作为左操作数。
答案 3 :(得分:0)
对象不能是" rvalue"或"左值"。如果不同类型的值(左值,右值,右值,右值等)适用于表达式,则用于访问对象,而不是对象本身。
在你的情况下,功能强制转换表达式Foo()
确实会产生一个临时对象作为右值。但是,在该临时对象的任何方法中,您可以使用表达式*this
,它将公开与左值相同的临时对象。换句话说,普遍认为临时物体是右值是明显不正确的。这总是一个用于访问对象的表达式的问题。
您可以在作业的左侧使用它,这并不奇怪。 "左值"要求仅适用于内置赋值运算符。对于重载赋值运算符,没有这样的要求,并且从来没有这样的要求。在您的情况下,您使用的是重载运算符。