【C++】运算符重载 | 赋值运算符重载

Ⅰ. 运算符重载

引入

❓什么叫运算符重载?

就是:运用函数,将现有的运算符重新定义,使其能满足各种自定义类型的运算。

回想一下,我们以前运算的对象是不是都是int、char这种内置类型?

那我们自定义的“preson”类型,想要进行加减运算,该怎么办呢?

这就需要运算符重载。

概念

运算符重载是具有特殊函数名的函数

也具有其返回值类型、函数名及参数列表。

函数名:关键字operator后面接需要重载的运算符符号。

格式:返回值类型 operator 操作符(参数列表)

1.常用的操作符有:+、-、*、/、++、--、=(赋值)、==(判断相等)、>、<、>=、<=等

2.有几个操作数,就有几个形参。

不过,当重载成员函数时,有一个形参是隐形的,即this指针。

说明:

1.不能通过连接其他符号来创建新的操作符。

如:operator@

2.重载操作符必须有一个类类型的参数。

如果参数里没有类类型,那运算符重载还有啥意义。

3.用于内置类型的运算符,其含义不能改变。

如:内置的 整型 +,不能改变其含义

4.作为类成员函数重载时,其形参看起来比操作数少1

因为成员函数的第一个参数为隐藏的this

(见下面的例子)

5.(笔试选择题常考)这5个运算符不能重载:

.* 点星运算符

: : 域运算符

sizeof

? : 条件运算符

. 点运算符

6.运算符重载写好了以后,直接用就行。编译器会自动调用函数。

Date& operator+=(int day){

}

d1+=100;    //直接用。调用会自动完成🤣

举例

class Date
{
public:Date(int year = 2000, int month = 1, int day = 1){_year = year;_month = month;_day = day;}                                 //需要注意的是,左操作数是this,指向调用函数的对象bool operator==(const Date& d)    //bool operator==(Date*this,const Date& d){return _year == d._year &&    //其实是this->_year==d._year_month == d._month &&_day == d._day;}
​
private:int _year;int _month;int _day;
};
int main()
{Date d1(2023, 8, 12);Date d2(2023, 8, 12);cout << (d2 == d1) << endl;
}

结果为:

 

 

Ⅱ. 赋值运算符重载

概念

赋值运算符重载作为类的6大成员函数之一,

负责将一个对象赋值给另一个对象。

如果我们不写,那编译器会自动生成

格式

T& operator =(const T& 参数)

 

说明:

1.参数类型为const T&。传引用可以提高传参效率。

2.返回类型为T&。

❓你可能会疑惑:这里只要完成赋值动作的话,返回类型为void不就可以了吗?

为什么要有返回值呢?

有返回值其实是为了支持连续赋值。

如”d1=d2=d3;“ 要想连续赋值,

那d2=d3在调用完函数以后要有一个返回值,这个返回值作为右操作数,参与到d1=…中去。

如果返回void,那d1=空,无法完成连续赋值。

所以,要想连续赋值,就得有返回值。

在返回时,我们尽量使用引用返回

因为能减少传参过程中的拷贝,效率更高。

不信我们来实验下,

通过对比 传值返回与传引用 调用拷贝构造函数 的次数,

来看 传引用究竟有没有减少拷贝!

实验组1:传值

class Date
{
public:Date(int year = 2000, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d)    //我们自己写一个拷贝构造函数{                      //这样,它每次被调用,都会打印出来cout << "我被调用了!" << endl;_year = d._year;_month = d._month;_day = d._day;}Date operator=(const Date& d)   //传值是可以的,但是没有引用好{                                //实验结果将为我们证明这一点_year = d._year;_month = d._month;_day = d._day;return *this;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2023, 8, 12);Date d2(2023, 8, 12);Date d3(2000, 1, 1);Date d4(2020, 1, 1);d1 = d2 =d3 = d4;
}
结果为:(这已经是被优化后的结果)

 

 

实验组2:传引用

...Date& operator=(const Date& d)   //传引用{_year = d._year;_month = d._month;_day = d._day;return *this;}...

结果为:

 

 

实验证明,传引用比传值调用拷贝构造函数的次数少,效率更高。

所以,我们能传引用的地方,就尽量传引用。

3.检测是否自己给自己赋值。

如果是”d1=d1;“那这样的赋值完全没意义。

为了更高效,我们用if语句来避免自己给自己赋值的情况。

Date& operator=(const Date& d){if (this != &d)    //加上判断{_year = d._year;_month = d._month;_day = d._day;return *this;}}

注:我们要用this去判断,不要用对象!

因为对象仅能判断值是否相等,而this能从地址判断它俩是否是同一个。

4.返回*this。

为什么可以返回*this?

我们知道,函数的局部变量是不能返回的,

因为局部变量在出了作用域就销毁了。

而这里不同,*this是 作用域在函数外面的 对象。

出作用域,对象并不会因此销毁。所以*this有效。

只能重载成成员函数

赋值运算符只能重载成成员函数,不能重载成全局函数。😥

因为如果不在类中实现,那编译器会生成一个默认的。

此时你在类外实现的全局运算符重载,就和默认的那个冲突了。

因此,赋值运算符必须定义成成员函数。

赋值or拷贝构造?

来看这个例子:这两种写法,分别是赋值还是拷贝构造?

  

其实都是拷贝构造!

赋值操作的是一个已存在的变量👌,而拷贝构造是定义一个新的变量。

默认赋值运算符重载

当你没有显示实现时,编译器会自动生成一个默认的赋值运算符重载,

以值的方式逐字节拷贝。

注:内置类型成员是直接赋值的,

而自定义类型成员变量需要调用 对应类的 赋值运算符重载 来完成赋值。

我们演示一下:

class Date {
public:Date(int year = 2000, int month = 1, int day = 1){this->_year = year;this->_month = month;this->_day = day;}
private:int _year;int _month;int _day;
};
​
int main(void)
{Date d1(2010,1,1);Date d2(2023,8,12);//我们并未实现,d1 = d2;   //但这里会自动调用 默认赋值运算符重载return 0;
}

结果:

 

❓既然默认生成的已经可以完成值的拷贝了,那还需要我们自己去实现吗?

如果是像日期类这种,是不需要的,值拷贝已经足够。

但如果涉及资源管理,

如动态内存分配、指针、打开的文件等,就得深拷贝,

这时就必须要自己去实现了。

(这里的原因和拷贝构造函数那儿是贯通的。)

原因再说明一下:

如果有指针,而默认的赋值运算符重载只能浅拷贝,

并不会再开一块指针指向的空间。

这就导致了两个指针指向同一块空间,彼此相互影响。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/46931.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ctfshow-web10 with rollup 绕过

0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 基本方法&#xff0c;到处点一点&#xff0c;点到取消的时候&#xff0c;突然发现&#xff0c;可以下载一个文件&#xff1a; 看到这个源码&#xff0c;可以看到只能是通过满足下面的条件来拿到flag&#xff…

多维时序 | MATLAB实现WOA-CNN-GRU-Attention多变量时间序列预测

多维时序 | MATLAB实现WOA-CNN-GRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现WOA-CNN-GRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现WOA-CNN-GRU-Attention多变量时间序列预测&#xff0c;WOA-CNN-GR…

SPSS--如何使用分层分析以及分层分析案例分享

分层分析&#xff1a;将资料按某个或某些需要控制的变量的不同分类进行分层&#xff0c;然后再估计暴露因子与某结局变量之间关系的一种资料分析方法。 分层分析的最重要的用途是评估和控制混杂因子所致的混杂偏倚。通过按混杂因子分层&#xff0c;可使每层内的两个比较组在所控…

三维重建 PyQt Python MRP 四视图(横断面,冠状面,矢状面,3D)

本文实现了 Python MPR 的 四视图&#xff0c;横断面&#xff0c;冠状面&#xff0c;矢状面&#xff0c;3D MPR(multi-planner reformation)也称多平面重建&#xff0c;多重面重建是将扫描范围内所有的轴位图像叠加起来再对某些标线标定的重组线所指定的组织进行冠状、矢状位、…

[Go版]算法通关村第十二关白银——字符串经典基础面试题

目录 反转专题题目&#xff1a;反转字符串思路分析&#xff1a;左右双指针 对向交换复杂度&#xff1a;时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( 1 ) O(1) O(1)Go代码 题目&#xff1a;反转字符串 II思路分析&#xff1a;K个一组反转思想&#xff08;找到每组的首尾索引…

redis 哨兵模式

目录 一、什么是哨兵模式 二、配置哨兵 三、启动哨兵 四、验证哨兵 五、复制延时 六、选举策略 一、什么是哨兵模式 哨兵也叫 sentinel&#xff0c;它的作用是能够在后台监控主机是否故障&#xff0c;如果故障了根据投票数自动将从库转换为主库。 二、配置哨兵 首先停止…

Day8 智慧商城

项目演示 项目收获 创建项目 调整初始化目录 1.删components里的所有文件 2.删views里的所有文件 3.router/index.js 删路由 删规则 import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const router new VueRouter({routes: [] })export default route…

【Spring专题】Spring之Bean的生命周期源码解析——阶段二(三)(属性填充之循环依赖底层原理解析)

目录 前置知识循环依赖的产生Spring里面的3个Map 课程内容一、只有一级缓存的推理演进1.1 直接将实例化后生成的对象放入到单例池里面1.1 引入一个中间Map存实例化后的早期对象&#xff08;疑似二级缓存&#xff09;1.3 解决1.2需要被代理的问题&#xff08;疑似二级缓存&#…

面试-快速学习计算机网络-UDP/TCP

1. OSI四层和七层映射 区别&#xff1a; 应用层&#xff0c;表示层&#xff0c;会话层合并为了应用层数据链路层和物理层合并为了网络接口层 2. TCP和UDP的区别&#xff1f; 总结&#xff1a; 1 . TCP 向上层提供面向连接的可靠服务 &#xff0c;UDP 向上层提供无连接不可靠服…

FL Studio21.1中文完整版Win/Mac

FL Studio All Plugins Edition【中文完整版 Win/Mac】适合音乐制作人/工作室使用&#xff0c;全套插件!&#xff08;20.9新增Vintage Chorus&#xff0c;Pitch Shifter变调插件&#xff09;FL Studio是超多顶级音乐人的启蒙首选&#xff01;包括百大DJ冠军Martin Garrix&…

21.0 CSS 介绍

1. CSS层叠样式表 1.1 CSS简介 CSS(层叠样式表): 是一种用于描述网页上元素外观和布局的样式标记语言. 它可以与HTML结合使用, 通过为HTML元素添加样式来改变其外观. CSS使用选择器来选择需要应用样式的元素, 并使用属性-值对来定义这些样式.1.2 CSS版本 CSS有多个版本, 每个…

AI 绘画Stable Diffusion 研究(十一)sd图生图功能详解-美女换装

免责声明: 本案例所用安装包免费提供&#xff0c;无任何盈利目的。 大家好&#xff0c;我是风雨无阻。 为了让大家更直观的了解图生图功能&#xff0c;明白图生图功能到底是干嘛的&#xff0c;能做什么事情&#xff1f;今天我们继续介绍图生图的实用案例-美女换装的制作。 对于…

ComPDFKit PDF SDK for Windows Crack

ComPDFKit PDF SDK for Windows Crack 添加了在创建文本框时调整默认属性的支持。 增加了对调整PDF大小时调整宽度的支持。 添加了对编辑文本时更多快捷方式的支持。 优化了文本输入&#xff0c;并将字体样式与原始文本相匹配。 在内容编辑器模式下复制和粘贴时优化了UI交互。 …

用于弥散加权MRI的关节各向异性维纳滤光片研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

三款远程控制软件对比,5大挑选指标:安全、稳定、易用、兼容、功能

陈老老老板&#x1f934; &#x1f9d9;‍♂️本文专栏&#xff1a;生活&#xff08;主要讲一下自己生活相关的内容&#xff09;生活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f9d9;‍♂️本文简述&#xff1a;三款远程控制软件对比&#xff0c;5大挑选指标&#xff1…

spring如何进行依赖注入,通过set方法把Dao注入到serves

1、选择Generate右键鼠标 你在service层后面方法的这些: 2、UserService配置文件的写法是怎样的&#xff1a; 3、我们在UserController中执行一下具体写法&#xff1a; 最后我们执行一下 &#xff1a; 4、这里可能出现空指针&#xff0c;因为你当前web层,因为你new这个对象根…

示例1:FreeRTOS移植详解_基于HAL库工程

1、开发环境 (1)Keil MDK: V5.38.0.0 (2)STM32CubeMX: V6.8.1 (3)MCU: STM32F103C8(F1系列软仿真最方便) (4)ARM编译器&#xff1a;V5(使用V6编译会报错) 2、移植准备工作 (1)用于移植FreeRTOS的基础工程。 时钟已配置好串口已配置好printf已经重定向到串口1 (2)FreeRT…

Android性能优化----执行时间优化

作者&#xff1a;lu人皆知 在APP做启动优化时&#xff0c;Application会做一些初始化的工作&#xff0c;但不要在Application中做耗时操作&#xff0c;然而有些初始化工作可能是很耗时的&#xff0c;那怎么办&#xff1f;初始化操作可以开启子线程来完成。 计算执行时间 常规…

MySQL的select ... where ...会加锁吗?

先说答案&#xff1a;不会。但select … where … lock in share mode会加锁。实验如下。 存储引擎innodb&#xff0c;MySQL版本5.7。 1&#xff1a;select … where … 如下图&#xff1a; 1&#xff1a;select … where … lock in share mode 如下图&#xff1a; 接着我…

【SpringCloud】SpringCloudAlibaba官网资料

出现原因 Spring Cloud Netflix Projects Entering Maintenance Mode 官网 博客 https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md官网 https://spring.io/projects/spring-cloud-alibaba#overview英文 https://github.com/alibaba/spring-cloud-…