大家好,我是苏貝,本篇博客带大家了解C++的运算符重载,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
1. 赋值运算符重载
学会了上面3种运算符重载后,赋值运算符重载该怎么写呢?下图是写在类里的
为什么最后要返回对象而非无返回值呢?因为我们对标的是内置类型的赋值运算符。问:下图的结果是什么?
上图中,先将j赋值给i,因此i == 2,(i=j)表达式有返回值,返回的是i而非i的拷贝。所以然后就变成了i=10,因此i==10,还是会返回i。
因此,赋值运算符重载后要返回对象,这样就可以连续赋值。返回值类型要不要加const?不加,如果加的话,赋值运算符左边(如const d1=d2)的d1就要是const修饰的,否则报错:权限放大
如何区分是赋值运算符重载和拷贝构造呢?看下图
拷贝构造:一个已存在的同类型的对象对新定义的对象初始化
赋值运算符重载:两个对象都已存在,将一个赋值给另一个
为了防止可能出现的d1=d1(将d1赋值给d1)的情况,将赋值运算符重载修改一下
a.赋值运算符重载格式
- 参数类型:const Date&,传递引用可以提高传参效率
- 返回值类型:Date&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
- 检测是否自己给自己赋值
- 返回*this :要复合连续赋值的含义
b. 编译器生成的默认赋值运算符重载
用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。
注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值
既然编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了,还需要自己实现吗?当然像日期类这样的类是没必要的,可在有些情况下会出错,如下面的栈(出错原因和拷贝构造函数一样)
运行崩溃,运行的时候出现这个错误,绝大多数都是未分配内存的原因,可以在申请空间的地方,初始化的地方多多检查。
我们来调试看看
我们在Stack类中没有写赋值运算符重载,因此编译器会自动生成一个。调试发现,在赋值完成后(编译器生成的赋值运算符重载,将对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝),st2的指向数组的指针_array和st1的指向数组的指针_array的值一样,即它们指向同一块内存空间。当对象生命周期结束时,C++编译系统自动调用析构函数(注意:先定义的对象后调用析构函数)。St2调用析构函数后,释放了数组空间,并将_array置为空。再St1调用析构函数,它的_array不为空,释放数组空间,但这块空间已被st2释放,两次释放报错
因此这时我们不能用编译器自动生成的赋值运算符重载,需要自己写
注意:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必须要实现,否则就是浅拷贝。
c. 赋值运算符只能重载成类的成员函数,不能重载成全局函数
赋值运算符重载成全局函数,可是如果类中不显式实现赋值运算符重载,那么编译器会自动生成一个。这样就会有2个赋值运算符重载,会冲突。因此赋值运算符重载只能作为类的成员函数,不能定义在全局域中
2. 前置++和后置++重载
前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载,C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递
先来实现+=的运算符重载(日期类)
实现了+=的运算符重载后,前置和后置++就都能很快写出来了
注意:
前置++:返回+1之后的结果。this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
后置++:先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this+1。而temp是临时对象,因此只能以值的方式返回,不能返回引用
好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️