c++拷贝构造与赋值运算符重载

目录

目录:

        1:拷贝构造

        2:赋值运算符重载

        


              

        前言:在上一章我们已经学习过了,构造与析构这两个默认成员函数了,接下来让我们一起来学习另外两个重要的默认成员函数。

        首先让我们来讲一下默认成员函数这个概念,所谓的默认成员函数,就是只要是类,类成员中就必定会含有这6个默认成员函数,空类也含有这6个默认成员函数。接下来让我们一起来学习拷贝构造与赋值重载吧。 

1:拷贝构造

        概念:函数名与类名相同,只有一个形参,且该形参是对本类类型对象的引用(一般用const修饰),在用已存在的类类型对象创建新对象时编译器自动调用。

        拷贝构造的特点:

        1:拷贝构造其实是构造函数的一种重载方式。(形参为该类类型对象的引用)

        2:拷贝构造只有一个参数,且该参数必须为该类类型对象的引用,如果是该类类型(传值),那么会形成无限递归,编译器在编译的时候会报错。 

        3: 当我们在一个类中并没有写拷贝构造函数的时候,编译器会自动生成一个默认的拷贝构造函数,这个默认的拷贝构造会按照字节拷贝的方式来进行拷贝,这种方式又被称为值拷贝(浅拷贝)。

        4:拷贝构造对于内置类型的成员完成值拷贝,对于自定义类型的成员调用它的拷贝构造,一般自定义类型成员的拷贝构造需要写一个深拷贝构造函数。

        注意:当类中没有申请内存资源的时候我们拷贝构造可写可不写,但是当类中申请了内存资源的时候我们就一定要写拷贝构造,不然我们程序会崩溃掉。

        我们通过图来解释上面的语法。

        

        那么为啥在传值的时候会报错呢?我们来分析一下 

        

         而当我们将拷贝构造的形参设置为,该类类型对象的引用时,引用并不是实参的拷贝,引用是实参的别名,所以不会形成无限的拷贝构造,也不会出错,真正才是拷贝构造规定的语法。

                

 对于语法3

        

             我们已经将我们写的拷贝构造函数给注释掉了,可是为什么我们在用d2拷贝d1的时候,还是完成了拷贝呢?这里是因为我们不写拷贝构造的时候,编译器会自动生成一个拷贝构造来完成值拷贝(浅拷贝)的工作,这也是默认成员函数牛逼的地方。

            可是当编译器会自动生成默认的拷贝构造的时候为什么我们还要学习拷贝构造函数的写法呢?

        这是因为呀,这个类并没有向内存中申请资源所以可以不用写拷贝构造利用编译器的拷贝构造就能够完成相应的功能,而当我们的类向编译器申请了内存资源呢?那又会发生什么呢?

        因为编译器的值拷贝是从内存中按照字节序来进行拷贝的,所以当我们的对象调用析构函数的时候,会对同一块空间完成两次析构,那么就会有非法访问内存的现象,编译器就会运行崩溃。

        如下图的描述:

        

       所以我们可以这样认为,我们学习拷贝构造,是为了当我们类对象向内存中申请空间的时候,我们就需要自己来写拷贝构造,这个用来解决申请内存空间的拷贝构造又叫做深拷贝。

        比如说下面的一个例子,我们定义一个Stack类

        

        假设我们使用的是它默认的构造函数。

        

        这里的程序就终止了,因为我们出变量的生命周期会自动调用它析构函数,所以就导致了释放两次同样的内存空间导致程序崩溃,调用析构函数的顺序与构造变量的顺序相反,在这里应该先调用的是st1的析构,在st调用的时候指针则会访问异常。

        所以我们应该自己来写一个构造函数,使得拷贝的时候并不指向同一块空间。

        如下代码 这也就可以使我们释放的时候并不是释放同一块空间

        当成员变量开辟空间的时候,我们需要自己来写拷贝构造函数,来完成深拷贝。

        下面是几个拷贝构造常用的几个场景

        1:用一个已知对象去创建另外一个对象

        2:函数参数类型为类类型对象

        3:函数返回值为类类型对象

        到这里我们的拷贝构造就讲解完毕了,然我们进入下一个知识点的讲解

        2:赋值运算符重载函数

        在讲赋值运算符重载函数之前,我们得先学一下运算符重载这个知识点。

        我们知道对于我们的内置类型(int char double....)变量来说,他们能够使用运算符来直接进行+-*/...等操作,这些变量的操作编译器会自动来识别,而对于自定义类型来说编译器并不能直接翻译,因为自定义类型比较复杂所以编译器并不能够识别,这也就需要程序员自己实现。

        运算符重载:用来解决自定义类型对象使用运算符的问题。

       函数名为:operator 运算符  

      其实运算符重载与普通函数的差别,只是运算符重载具有特定的函数名,其他的与普通函数一样。我们用日期类来举例,运算符重载的定义。

        

        这就是一个日期类的运算符重载的定义,与普通函数并没有差别很大。

        我们在定义运算符重载的时候需要注意的有以下几点

        1:我们并不能用operator运算符来增加新的运算符,必须与我们内置类型相似的。

        2:运算符重载的一个参数必须是类类型的,因为运算符重载是用来解决自定义类型的使用运算符的问题。

        3:我们不能改变运算符的意思,比如说operator+,我们并不能改变原有+的含义。

        4:当运算符重载函数作为类成员函数的时候,函数的形参比操作数永远少1,因为我们会将左操作数当作this指针传进来 。

        5: .* :: sizeof  ?: .这5个操作数并不能形成运算符重载

        有了运算符重载这个知识,我们就可以来学习默认成员函数的赋值运算符重载函数了,

        其实赋值运算符重载函数,也就是operator= 这个函数名的实现。

        赋值运算符重载函数当我们不写的时候编译器会默认的生成一个值拷贝,赋值运算符对于成员向内存开辟了空间那么我们的赋值运算符就要写深拷贝,与拷贝构造类似需要自己开空间。

        当我们使用赋值运算符重载函数的时候必须在类中实现不能在类外,因为当我们在类外实现的时候,因为编译器会看到我们类中并没有显示的写赋值运算符重载函数,所以就会默认生成,导致会有两个赋值运算符重载函数,会有冲突。

        赋值运算符重载的规则

        1:返回值为const 类名&   

        2:参数也是 const 类名&   用引用来提高效率

        3:返会*this,*this是左边操作数如  j = i+=5;  这里i+=5返回的是i。

        4:检查自己是否给自己赋值(自己给自己赋值不会报错,但是这样没什么意义)

        

        关于前置++与后置++的区分   i++,++i

        我们知道++运算符的函数名应该为  operator++,那么我们该如何来区分 前置与后置呢?

       在这里我们可能需要利用函数重载的概念来区分,因为他们两的函数名相同,所以我们可以利用参数使得它们区分。

        c++规定,在参数中加了如:operator(int)有形参的就是后置++,未有形参的就是前置++

     

    

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

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

相关文章

【ARM Trace32(劳特巴赫) 使用介绍 2 -- Trace32 cmm 脚本基本语法及常用命令】

文章目录 Trace32 CMM 概述1.1 Trace32 系统命令 SYStem1.1.1 Trace32 SYStem.CONFIG1.1.2 SYStem.MemAccess1.1.3 SYStem.Mode1.1.3.1 TRST-Resets the JTAG TAP controller and the CPU internal debug logic1.1.3.2 SRST- Resets the CPU core and peripherals 1.2 Trace32 …

Azure - 自动化机器学习AutoML Azure使用详解

目录 一、AutoML是如何工作的?二、何时考虑AutoML?三、AutoML助力训练与集成过程四、实战案例五、总结 自动化机器学习,简称为AutoML,旨在将机器学习模型的开发中繁琐且重复的任务自动化。这使得数据科学家、分析师以及开发人员能…

ThinkPad电脑HDMI接口失灵如何解决?

ThinkPad电脑HDMI接口失灵如何解决? 如果平时正常使用的外接显示器,某天突然无法使用了,重新插拔依然无信号的话,可以打开系统的设备管理器(快捷键winx),首先看一下监视器的识别情况&#xff0c…

Istio 实战

文章目录 Istio流量管理分享会【1】什么是istio?【2】istio 可以干什么?【3】业务中的痛点?【4】istio 高级流量管理5.1 istio 组件介绍与原理5.2 sidercar何时注入?如何控制是否注入?5.3 查看sidecar 容器插入的容器中的iptablesDestination RuleVirtual ServiceGateways…

Camtasia Mac 2023版怎么给视频加字幕

在视频制作过程中,字幕和马赛克是两项非常常用的编辑功能,添加字幕可以提高观众的观看体验,添加马赛克可以保护视频创作者不想公开的画面内容。Camtasia作为一款知名的视频制作软件,在具备基本的录制和视频编辑功能的同时&#xf…

win10安装spark

一、进入spark下载页面 连接 Downloads | Apache Spark 二、解压下载后的.tgz文件 直接解压即可 三、运行 运行bin目录下的 spark-shell.cmd 提示 Did not find winutils.exe: java.io.FileNotFoundException: java.io.FileNotFoundException: HADOOP_HOME and hadoop.hom…

二蛋赠书六期:《Linux管理入门经典(第8版)》

前言 大家好!我是二蛋,一个热爱技术、乐于分享的工程师。在过去的几年里,我一直通过各种渠道与大家分享技术知识和经验。我深知,每一位技术人员都对自己的技能提升和职业发展有着热切的期待。因此,我非常感激大家一直…

[量化投资-学习笔记002]Python+TDengine从零开始搭建量化分析平台-MA均线的多种实现方式

MA 均线时最基本的技术指标,也是最简单,最不常用的(通常使用EMA、SMA)。 以下用两种不同的计算方法和两种不同的画图方法进行展示和说明。 MA 均线指标公式 MA (N)(C1 C2 C3 …C N )/N目录 方式一1.SQL 直接查询均值2.使用 pyp…

RHCE---shell脚本编程sed

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 Liunx中筛选文本时常用的命令,常常会被提及文本三剑客,前文我们学习了文本三剑客中的grep 命令,除了grep命令我们也常用到sed命令,sed命令有…

window系统修改rabbitmq 默认端口

安装完rabbitmq之后,默认的client端口是5672, 控制台访问端口是15672,rabbitmq管理工具启动之后在浏览器中输入地址: ​ ​http://localhost:15672/​​​ 就可以访问后台​ ​​​, 默认管理员账号:guest 密码&#x…

【0基础学Java第四课】-- 逻辑控制

4. 逻辑控制 4.1 顺序结构4.2 分支结构4.2.1 if语句判断一个数字是奇数还是偶数判断一个数字是正数,负数,还是零判断一个年份是否为闰年 4.2.2 switch 语句 4.3 while循环打印 1 - 10 的数字计算 1 - 100 的和计算 5 的阶乘计算1!2&#xff0…

Openssl数据安全传输平台014:OCCI环境搭建和使用:Centos8-Oracle19c代码跑通 + Window代码没跑通(不影响本项目)

文章目录 0 代码仓库1 启动Centos oracle数据库2 Winsows安装配置OCCI库2.1 下载文件2.2 VS 配置2.2.1 VC包含目录2.2.2 VC库目录2.2.3 连接器-附加依赖项2.2.4 代码测试-Oracle11g2.2.4.1 准备2.2.4.2 代码测试 3 Centos安装配置occi库3.0 强调3.1 下载instantclient库文件压缩…

ubuntu 安装串口工具和添加虚拟串口

目录 一、串口工具安装 二、使用Windows本身虚拟的串口 (一)添加串口 1、保证虚拟机是关闭状态,打开“虚拟机设置”,点击“添加”。 2、选中“串行端口”,点击“完成”。 3、选中刚添加的串口,下拉选…

python快速入门

语法结构 基本输出 使用print函数来完成基本输出 print("I am xl")注释 单行注释使用# 多行注释 多行注释""" 多行注释 """缩进 python和其他语言最大的区别就是用缩进来区分子代码区域而不是大括号 续行 使用\符号来完成续行…

宠物用品小程序

近年来,越来越多的人选择将宠物视为家庭的一员,为宠物购买各种用品成为了一项重要的消费活动。因此,宠物用品小程序应运而生,为消费者提供了一个便捷的购买平台,同时也为宠物带来了更加幸福的生活。 登录乔拓云平台进入…

京东平台数据分析(京东销量):2023年9月京东吸尘器行业品牌销售排行榜

鲸参谋监测的京东平台9月份吸尘器市场销售数据已出炉! 根据鲸参谋电商数据分析平台的相关数据显示,今年9月,京东吸尘器的销量为19万,环比下滑约12%,同比下滑约25%;销售额为1.2亿,环比下滑约11%&…

前端实现埋点监控

前端实现埋点&监控 实现埋点功能的意义主要体现在以下几个方面: 数据采集:埋点是数据采集领域(尤其是用户行为数据采集领域)的术语,它针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。通过埋…

本地生活商家用批量剪辑有用吗?

可以用,现在很多本地生活商家,都会通过借助批量剪辑工具来提升视频的曝光量,从而带动店铺的客流量。 推荐本地生活商家使用超级编导批量剪辑工具,这是一款0基础小白也可以很快上手的批量剪辑工具,剪辑页面布局以及功能…

python_PyQt5日周月K线纵向对齐显示_3_聚焦某段图形

目录 写在前面: 结果显示: 代码: 写在前面: “PyQt5日周月K线纵向对齐显示”,将分三篇博文描述 1 数据处理。将数据处理成适合图形显示的格式。(已写,请看往期博文) 2 显示工具…

不小心commit错误代码,还没push的回滚解决方法

命令:git reset --soft HEAD^ 第一步:找到项目所在文件夹 第二步,右键点击git base here 第三步,命令行输入git reset --soft HEAD^ 回车即可