c++递增运算符++的重载(--同理)

1.写++之前先了解++a和a++的区别

    int a=10;
	cout<<"cout<<a++:  "<<a++<<endl;//10
	cout<<"cout<<a:  "<<a<<endl;//11
	
	int b=10;
	cout<<"cout<<++b:  "<<++b<<endl;//11
	cout<<"cout<<b:  "<<b<<endl;//11

在这里插入图片描述
a++是先赋值,再加1,再把+1后的值赋给a
++a是先加一,再把+1后的值赋给a, 但是最终的a结果都一样,都是加一后的新数,但是再和<<配合使用的时候就会出现上面的错误。

前置++和后置++,有4点不同:返回类型不同、形参不同、代码不同 前置和后置均值的是++号的前置和后置

1.返回类型不同

前置++的返回类型是左值引用,后置++的返回类型const右值。而左值和右值,决定了前置++和后置++的用法。

++a的返回类型为什么是引用呢?

这样做的原因应该就是:与内置类型的行为保持一致。前置++返回的总是被自增的对象本身。因此,++(++a)的效果就是a被自增两次。
但(a++)++就会报错(会显示表达式必须是可修改的左值),原因就是a++的返回类型不是引用,第一次++后返回的对象是临时对象,不是本体,而那个临时对象很快会被释放内存,我们根本就找不到第二次++的对象。

2.形参的区别

前置++没有形参,而后置++有一个int形参,但是该形参也没有被用到。很奇怪,难道有什么特殊的用意?

其实也没有特殊的用意,占位参数,只是为了绕过语法的限制。

前置++与后置++的操作符重载函数,函数原型必须不同。否则就违反了“重载函数必须拥有不同的函数原型”的语法规定。再说了,俩函数一样,我编译器怎么知道调用哪个?

虽然前置++与后置++的返回类型不同,但是返回类型不属于函数原型。为了绕过语法限制,只好给后置++增加了一个int形参。占位参数

原因就是这么简单,真的没其他特殊用意。

3.代码实现的区别

前置++的实现比较简单,自增之后,将this返回即可。需要注意的是,**一定要返回this**。因为是引用返回,所以返回本身就行。

后置++的实现稍微麻烦一些。因为要返回自增之前的对象,所以先将对象拷贝一份,再进行自增,最后返回那个拷贝。因此无法使用引用返回,因为我们不能返回一个局部变量,为什么不行这里不再赘述。

C++Primer中(P132)有这样简介的描述:

前置版本将对象本身作为左值返回,后置版本则将原始对象的副本作为右值返回,两种运算符必须作用于左值运算对象。后置版本需要拷贝副本,所以会影响程序的性能。

++类型的重载运算符放在类内,用类的成员函数实现最合适,全局函数有诸多不便,下面会一一介绍。

上面也已经介绍了,++类型的重载分为前置重载和后置重载。(必须依托类)

#include <iostream>
using namespace std;
class person {
public:
	//<<的重载函数,cout相当于调用了<<这个函数,
	//设置为友元函数,不然无法访问person的私有数据成员。顺便复习一下友元知识
	friend ostream& operator<<(ostream& cout, person p);
	person(int a, int b) {
		m_A = a;
		m_B = b;
	}
	//前置++,(++a)内置引用属性,所以我们重载后的也要赋予其引用返回的属性
	person &operator++() {
		m_A++;//至于这里是++m_A还是m_A都可以,原理性的东西一想就行。
		m_B++;
		return *this;//返回调用当前函数的对象实体
	}
	//后置++(a++)不用引用,不要破坏原有的机理,我们的目的就是做一个高仿,不是重新定义机理,容易乱
	person operator++(int) {
		person temp = *this;//因为要返回自增前的对象,所以先拷贝一份,待会儿再把那个备份返回去。
		m_A++;//++m_A也行,没必要在这纠结这么多。
		m_B++;
		return temp;
	}
private:
	int m_A;
	int m_B;
};
//<<运算符的重载,
ostream& operator<<(ostream &cout,person p) {
	cout << p.m_A << "    "<< p.m_B << endl;
	return cout;
}
int main()
{   person p1(1, 1);
	cout << "cout<<p++ : "<<p1++; //如果上面的<<重载函数形参列表的person写成引用的话就不能写成 cout<<p++;
	//因为我后者++返回的是一个局部变量temp,而temp是一个临时对象,而我不能引用一个临时对象,,临时对象只能传值传进去
	cout << "p1自增后的值:"<<p1;

	person p2(1, 1);
	cout <<"cout<<++p2:"<<++p2;//前置引用有天生的引用属性,先++,再返回p2本体
	cout <<"p2自增后的值:"<< p2;//而不是像后置那样返回一个原值的拷贝。
}

在这里插入图片描述

结果分析:
我们发现,若单独输出自增后的值相同,但是如果将自增和cout输出语句一块使用就会出现差异,并且此差异和重载前一模一样,所以此重载函数符合我们的要求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ad_m1n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值