我有一个名为YourClass的类。我的问题是为什么编译器不会为跟随代码生成错误?
YourClass AMethod(){ return YourClass();}
AMethod() = YourClass();
[在这种情况下IN MY OPINION AMethod只返回一个值(我的意思是它没有l值)。]
编辑: 如果我能做到这一点,为什么我不能做以下
int AMethod(){ return a;}
AMethod() = 5;
答案 0 :(得分:3)
EDIT1:我想我第一次想念这个问题。
标准说: 3.10左值和右值
调用函数的结果 不返回引用是一个 右值。用户定义的运算符是 功能,以及是否这样的运营商 期望或产生左值确定 通过参数和返回类型。
除了用户定义的类型和基元类型相同外,该标准在本段中没有说明。如果函数的返回不是引用,则它不是l值。然而,在同一页面上有一个有趣的评论:
47)表达如调用 构造函数和函数 返回类类型引用对象, 并且实现可以调用a 成员函数对这些对象,但 表达式不是左值。
所以基本上在你的例子中:
AMethod() = YourClass();
AMethod返回用户定义的类型,其函数为:
AMethod().operator=(YourClass());
已执行。不过,它不是一个l值。实际上,您可以在C ++中使用空语句,或者只包含r值的语句!:
5;;; // correct C++ code!
<强> EDIT2:强>
考虑这个例子:
if( &(YourClass() + YourClass()) == &YourClass() )
{
....
}
表达式&(YourClass() + YourClass())
必须产生l值,因此整个表达式变得正确。它在VC上编译得很好,但它给出了一点警告:
warning C4238: nonstandard extension used : class rvalue used as lvalue
显然C ++标准上面的行是错的,但VC只允许它!
因为你问过这个问题。首先,YourClass
返回AMethod
的新实例。然后,它被分配另一个新实例。当然,在C ++中你可以说出你想要的东西。因此,要阻止赋值语句,只需返回const YourClass
。在这种情况下,对象仅变为“可读”:
const YourClass AMethod(){ return YourClass();}
如果您正在重载二元运算符,这是相同的。例如,如果您为某个类重载operator+
,那么您可以使用const
或不使用它。
// '+' operator is defined as a friend operator not a member.
friend YourClass operator+(const YourClass& lhs, const YourClass& rhs)
{
...
}
如果你这样做,你可能会有如下无意义的陈述:
(a + b) = c;
如果表达式(a + b)
没有用,因为它只表示一个值,而不是我们控制的变量,它会产生一个临时变量。
答案 1 :(得分:2)
AMethod
会返回 rvalue 。在C ++中,您可以在用户定义类型的右值上调用成员函数,甚至修改成员函数。有时这正是你想要的。
os.get_disk_accessor(0).wipe(); // wipe() might not be a const member function
但是,您无法调用内置类型的rvalues上的操作:
int f();
f() = 5; // won't compile
++f(); // won't either
答案 2 :(得分:0)
表达式
AMethod()
创建并返回一个类对象和表达式
AMethod() = YourClass();
创建第二个对象并将其分配给第一个对象。
答案 3 :(得分:0)
我认为第1版的编译是因为YourClass有一个默认的构造函数,析构函数,复制构造函数和 赋值运算符 ,它们调用了AMethod()= YourClass();. int AMethod(){return a;} AMethod()= 5; 此代码无法编译,因为没有右值。