5

看下面的代码:

#include <iostream>
using namespace std;

class Widet{
public:
    Widet(int val = 0):value(val)
    {

    }

    Widet& operator=(Widet &rhs)
    {
        value = rhs.value;
        return *this;
    }
    int getValue()
    {
        return value;
    }
private:
    int value;
};

int main()
{
    Widet obj1(1);
    Widet obj2(2);
    Widet obj3(0);
    (obj3 = obj2) = obj1;
    cout << "obj3 = " << obj3.getValue() << endl;
}

代码运行成功,输出为(使用VS2008):

在此处输入图像描述

当我让 operator= 返回一个值而不是引用时:

Widet operator=(Widet &rhs)
{
    value = rhs.value;
    return *this;
}

它也成功运行,输出为:

在此处输入图像描述

我的问题是:为什么第二个代码运行良好?我们不应该得到一个错误吗?

为什么返回对 *this 的引用而不是 *this 是一个好习惯?

4

7 回答 7

8

为什么第二个代码运行良好?我们不应该得到错误吗?

因为它是完全有效的代码。它返回对象的临时副本,并且您可以operator=()在临时对象上调用成员函数(包括 ),因此不会出错。

如果对象不可复制,您将收到错误消息。

为什么返回对 *this 的引用而不是 *this 是一个好习惯?

因为并非所有对象都是可复制的,而且有些对象的复制成本很高。您可以引用任何对象,并且引用总是很便宜传递。

于 2012-08-20T13:32:28.113 回答
3

通常,您返回一个引用,以便可以将=运算符用作左值。

于 2012-08-20T13:24:52.573 回答
3

当您不返回引用时,(obj3 = obj2)提供obj3. 副本从中获取值obj1并被删除,而obje3不会受到第二次赋值的影响。

于 2012-08-20T13:31:36.910 回答
2

为什么第二个代码运行良好?我们不应该得到错误吗?

它运行是因为非常量成员函数也可以在(非常量)类右值上调用。第二个版本operator=返回一个非常量类右值,因此实际上,您分配给临时值,而将先前的值留在obj3变量中。

因此,没有错误。

于 2012-08-20T13:31:29.730 回答
0

在第二个示例中,您创建一个临时的(Obj3 的副本,由 operator= 返回)并将 Obj1 分配给它。然后它立即被破坏。Obj3 仍然是第一次分配的结果 - Obj3 = Obj2

于 2012-08-20T13:29:34.693 回答
0

从 operator=() 返回引用可以启用如下表达式:

a=b=c;

当您不需要它时,返回一个值可能是多余的。它可能会导致额外的复制构造函数/析构函数调用。否则,返回一个值是完全有效的 C++。如果我错了,请纠正我,但我认为在 C++11 中按值返回并不是什么大问题,因为移动语义。

于 2012-08-20T13:30:23.510 回答
0
(obj3 = obj2)

可以认为是obj3operator=(obj2)//假设。
由于您已将 obj2 作为参数传递,因此您的运算符重载会将 obj2.value 复制到 obj3.value 中。

(obj3 = obj2) = obj1;
from 返回后,会返回operator=obj3 ( *this,temporary copy)。
因此,等效代码obj3=obj1将再次调用operator=ofobj3并将值重置obj3.valueobj1.valueie 1

于 2012-08-20T13:36:48.750 回答