将对象分配给方法调用

时间:2009-10-01 21:54:40

标签: c++

我有一个名为YourClass的类。我的问题是为什么编译器不会为跟随代码生成错误?

YourClass AMethod(){ return YourClass();}
AMethod() = YourClass();

[在这种情况下IN MY OPINION AMethod只返回一个值(我的意思是它没有l值)。]

编辑: 如果我能做到这一点,为什么我不能做以下

int AMethod(){ return a;}
AMethod() = 5;

4 个答案:

答案 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; 此代码无法编译,因为没有右值。