为什么重载运算符要返回自身的引用

本文topic
为什么重载运算符一定要返回自身引用
结论

  1. 可以实现和cout一样连续调用
  2. 避免了一次拷贝构造和析构,提升程序性能

正文
重载运算符为什么一定要返回自身的引用的,返回void的不行吗?
返回自身类型不行吗为什么一定要返回自身引用呢?

为了解释清楚这个问题,我们拿赋值运算符举例

首先定义一个简单的Number类

class Number
{
private:
    int num;
    static int count;//用于计算调用了几次构造函数,包括拷贝构造函数
public:

    Number(int n=0):num(n)//默认参数为零,可以同时当默认构造函数使用
    {
        count++;//每次调用一次加1
        cout<<"Count of constructed class Number: "<<count<<endl;
    }
    
    Number(const Number& other)//自定义拷贝构造函数
    {
        count++;
        num=other.num;
        cout<<"Count of constructed(Copy) class Number:"<<count<<endl;
    }
    
    ~Number()
    {
        cout<<"Destructor has been called"<<endl;
    }

    void printNumber()
    {
     	cout<<"num的值:"<<num<<endl;
    }    
};
int Number::count=0;//count初始值设为0


对于Numbe这个类,我们一般都是这样来重载赋值运算符的

Number& operator=(const Number& other)
{
	num=other.num;
	return *this;
}

那么为什么一定要返回自身引用呢?
我们可以将这问题分解为两个问题

  1. 一是为什么要返回自身类型
  2. 而是为什么要还一定要返回自身的引用

我们可以思考一下,如果没有重载赋值运算符,使用普通的函数,我们让一个Number对象等于另外Number对象是这样的

void equal(const Number& other)//写在类里面
{
	num=other.num;
}

在main里使用一下

int main()
{
	Number n1(1);
	Number n2;
	n2.equal(n1);
	n2.printNumber();
}	

输出结果:
在这里插入图片描述
equal函数调用成功

操作符本质上就是函数,那么我们看看能不呢重载一个=的操作符来实现同样的功能
我们来改造一下equal函数

void operator=(const Number& other)//只是改了函数名,将“equal”改为“operator=”
{
	num=other.num;
}

调用

int main()
{
    Number n1(1);
    Number n2;
    //n2.equal(n1);
    //n2.printNumber();

    n2=n1;
    n2.printNumber();
}

运行结果
在这里插入图片描述
赋值操作符调用成功
那么问题来了,既然void就可以,为什么开头的重载函数要返回Number类型呢?

如果我们回顾一下int类型的赋值我们可以发现它是可以连续赋值的

int main()
{
    int i1=2,i2=2,i3=3;
    i1=i2=i3;  //可以理解为i1=i2,此时i1的值为2,然后i1又等于i3
    cout<<i1<<endl;
}

运行结果为
在这里插入图片描述
此时可以发现(i1=i2)它是有一个返回类型的,返回的类型就是他本身的类型,所以可以实现连续赋值
而我们写的Numer类就不能实现该连续赋值

int main()
{
    Number n1(1),n2(2),n3(3);
    n1=n2=n3;//如果我们这么写,编译器会报错
}

那么改为返回自身类型呢

Number operator=(const Number& other)
{
	num=other.num;
	return *this;
}
int main()
{
    Number n1(1),n2(2),n3(3);
    n1=n2=n3;
    n1.printNumber();// 运行结果值为3
}

可以发现一旦改为返回自身类型就可以实现连续赋值了
所以返回自身类型,是为了该操作符能连续使用。

第二问题,为什么要返回Number类型的引用呢?
我们可以同时调用一下文章开头返回Number引用的重载运算符和上面写的不带引用的重载运算符,用同样的代码来测试一下有什么区别。
测试代码均为


int main()
{
    Number n1(1),n2(2);
    n1=n2;
    n1.printNumber();
}

首先是不带引用的运行结果
在这里插入图片描述
而这是带引用的运行结果在这里插入图片描述
可以发现带引用的运行结果减少一次拷贝构造和析构。
那么为什么会减少呢?

	Number n1(1),n2(2);
    n1=n2;
    n1.printNumber();

因为上面运行代码中,带引用的话,只新建了n1和n2两个对象,当n1=n2的时候,因为返回的n1的引用,所以返回还是n1这个对象。即(n1=n2)的值,还是n1,只不过n1里面的变量值变了。
而不带引用时,在赋值重载函数中,return *this的时候,用n1拷贝构造了一个临时对象,然后因为没有左值接受这个临时变量,所以又被析构了。即(n1=n2)的值是一个临时变量,刚新建,就被析构了。所以多了一个拷贝构造函数和析构函数,因此返回引用类型会带来了一点性能的提升。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值