当前位置: 首页 > news >正文

【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;
}

结果:

 

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

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

但如果涉及资源管理,

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

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

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

原因再说明一下:

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

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

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

 

相关文章:

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

Ⅰ. 运算符重载 引入 ❓什么叫运算符重载&#xff1f; 就是&#xff1a;运用函数&#xff0c;将现有的运算符重新定义&#xff0c;使其能满足各种自定义类型的运算。 回想一下&#xff0c;我们以前运算的对象是不是都是int、char这种内置类型&#xff1f; 那我们自定义的“…...

Python学习 -- 类对象从创建到常用函数

在Python编程中&#xff0c;类是一种强大的工具&#xff0c;用于创建具有共同属性和行为的对象。本篇博客将详细介绍Python中类和对象的创建&#xff0c;类的属性和方法&#xff0c;以及一些常用的类函数&#xff0c;通过丰富的代码例子来帮助读者深入理解。 一、类和对象的创…...

数组分割(2023省蓝桥杯)n种讨论 JAVA

目录 1、题目描述&#xff1a;2、前言&#xff1a;3、动态规划&#xff08;bug)&#xff1a;3、递归 剪枝&#xff08;超时&#xff09;&#xff1a;4、数学&#xff08;正解&#xff09;&#xff1a; 1、题目描述&#xff1a; 小蓝有一个长度为 N 的数组 A [A0, A1,…, AN−…...

很好的启用window10专业版系统自带的远程桌面

启用window10专业版系统自带的远程桌面 文章目录 启用window10专业版系统自带的远程桌面前言1.找到远程桌面的开关2. 找到“应用”项目3. 打开需要远程操作的电脑远程桌面功能 总结 前言 Windows操作系统作为应用最广泛的个人电脑操作系统&#xff0c;在我们身边几乎随处可见。…...

TCP定制协议,序列化和反序列化

目录 前言 1.理解协议 2.网络版本计算器 2.1设计思路 2.2接口设计 2.3代码实现&#xff1a; 2.4编译测试 总结 前言 在之前的文章中&#xff0c;我们说TCP是面向字节流的&#xff0c;但是可能对于面向字节流这个概念&#xff0c;其实并不理解的&#xff0c;今天我们要介…...

YOLOX在启智AI GPU/CPU平台部署笔记

文章目录 1. 概述2. 部署2.1 拉取YOLOX源码2.2 拉取模型文件yolox_s.pth2.3 安装依赖包2.4 安装yolox2.5 测试运行2.6 运行报错处理2.6.1 ImportError: libGL.so.1: cannot open shared object file: No such file or directory2.6.2 ImportError: libgthread-2.0.so.0: cannot…...

23种设计模式攻关

&#x1f44d;一、创建者模式 &#x1f516;1.1、单例模式 单例模式&#xff08;Singleton Pattern&#xff09;&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供全局访问点。 在某些情况下&#xff0c;我们需要确保一个类只能有一个实例&#xff0c;比如数据库连接…...

【jsthreeJS】入门three,并实现3D汽车展示厅,附带全码

首先放个最终效果图&#xff1a; 三维&#xff08;3D&#xff09;概念&#xff1a; 三维&#xff08;3D&#xff09;是一个描述物体在三个空间坐标轴上的位置和形态的概念。相比于二维&#xff08;2D&#xff09;只有长度和宽度的平面&#xff0c;三维增加了高度或深度这一维度…...

unity将结构体/列表与json字符串相互转化

编写Unity程序时&#xff0c;面对大量需要传输或者保存的数据时&#xff0c;为了避免编写重复的代码&#xff0c;故采用NewtonJson插件来将定义好的结构体以及列表等转为json字符串来进行保存和传输。 具体代码如下&#xff1a; using System; using System.IO; using Newtons…...

【Vue】vue2项目使用swiper轮播图2023年8月21日实战保姆级教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、npm 下载swiper二、使用步骤1.引入库声明变量2.编写页面3.执行js 总结 前言 swiper轮播图官网 参考文章&#xff0c;最好先看完他的介绍&#xff0c;再看…...

【算法日志】贪心算法刷题:单调递增数列,贪心算法总结(day32)

代码随想录刷题60Day 目录 前言 单调递增数列 贪心算法总结 前言 今天是贪心算法刷题的最后一天&#xff0c;今天本来是打算刷两道题&#xff0c;其中的一道hard题做了好久都没有做出来(主要思路错了)。然后再总结一下。 单调递增数列 int monotoneIncreasingDigits(int n…...

MATLAB算法实战应用案例精讲-【深度学习】模型压缩

目录 模型压缩概述 1. 为什么需要模型压缩 2. 模型压缩的基本方法 Patient-KD 1. Patient-KD 简介...

Matlab使用

Matlab使用 界面介绍 新建脚本&#xff1a;实际上就是新建一个新建后缀为.m的文件 新建编辑器&#xff1a;ctrlN 打开&#xff1a;打开最近文件&#xff0c;以找到最近写过的文件 点击路径&#xff0c;切换当前文件夹 预设&#xff1a;定制习惯用的界面 常见简单指令 ;…...

BladeX多数据源配置

启用多租户数据库隔离&#xff0c;会默认关闭mybatis-plus多数据源插件的启动&#xff0c;从而使用自定义的数据源识别 若不需要租户数据库隔离只需要字段隔离&#xff0c;而又需要用到多数据源的情况&#xff0c;需要前往LauncherService单独配置 数据源切换失败 详情请看说明…...

go里面关于超时的设计

设想一下你在接收源源不断的数据&#xff0c;如果有700ms没有收到&#xff0c;则认为是一个超时&#xff0c;需要做出处理。 逻辑上可以设计一个grouting,里面放一个通道&#xff0c;每收到一条数据进行相应处理。通道中夹杂一个timer定时器的处理&#xff0c;若通道在700ms内…...

Qt下使用ModbusTcp通信协议进行PLC线圈/保持寄存器的读写(32位有符号数)

文章目录 前言一、引入Modbus模块二、Modbus设备的连接三、各寄存器数据的读取四、各寄存器数据的写入五、示例完整代码总结 前言 本文主要讲述了使用Qt的Modbus模块来进行ModbusTcp的通信&#xff0c;实现对PLC的线圈寄存器和保持寄存器的读写&#xff0c;基于TCP/IP的Modbus…...

ElasticSearch学习2

1、索引的操作 1、创建索引 对ES的操作其实就是发送一个restful请求&#xff0c;kibana中在DevTools中进行ES操作 创建索引时需要注意ES的版本&#xff0c;不同版本的ES创建索引的语句略有差别&#xff0c;会导致失败 如下创建一个名为people的索引&#xff0c;settings&…...

3D角色展示

先看效果&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>3D卡片悬停</title><style>font-face {font-family: "Exoct";src: url("htt…...

前端面试:【Angular】打造强大Web应用的全栈框架

嗨&#xff0c;亲爱的Angular探险家&#xff01;在前端开发的旅程中&#xff0c;有一个全栈框架&#xff0c;那就是Angular。Angular提供了模块化、组件化、依赖注入、路由和RxJS等特性&#xff0c;助力你构建强大、可扩展的Web应用。 1. 什么是Angular&#xff1f; Angular是…...

数据结构:栈和队列

文章目录 一、栈1.栈的概念及结构1.栈的概念及结构2.栈的实现 2.栈的顺序表实现1.栈的结构体和实现的功能函数2.栈的初始化&#xff0c;入栈和出栈操作3.栈的其他操作 3.栈的链表实现1.栈的结构体和实现的功能函数2.栈功能函数的实现 二、队列1.队列的概念及结构1.队列的概念及…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...