类的默认成员函数——拷贝构造函数

1.概念引入

在现实生活中,如果有两个兄弟长得一模一样,我们就称其为双胞胎

 当我们创建了一个新的对象,需要用同类型的对象拷贝并初始化,就要用到拷贝构造函数

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。MyClass(const MyClass& other)

2.特征

1.拷贝构造函数是构造函数的一个重载形式

2.拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。 

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2(d1);//或者写成 Date d2 = d1;return 0;
}

3.若未显示定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储,按字节序完成拷贝,这种拷贝叫浅拷贝,或者值拷贝。与之相应的叫做深拷贝

在下面这个案例中,用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数,但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数 

class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time(const Time& t){_hour = t._hour;_minute = t._minute;_second = t._second;cout << "Time::Time(const Time&)" << endl;}
private:int _hour;int _minute;int _second;
};class Date
{
private://内置类型int _year = 1970;int _month = 1;int _day = 1;//自定义类型Time _t;
};int main()
{Date d1;Date d2(d1);return 0;
}

下面对浅拷贝和深拷贝分别做一个简单的介绍

浅拷贝

  • 浅拷贝仅仅复制对象的第一层属性。
  • 对于基本数据类型(如数字、字符串、布尔值等),浅拷贝会直接复制其值
  • 对于引用类型(如数组、对象等),浅拷贝不会复制引用类型数据本身,而是复制引用的地址。这意味着原始对象和拷贝对象在引用类型数据上共享同一块内存地址。
  • 因此,如果修改原始对象的引用类型属性,拷贝对象的相应属性也会受到影响。

深拷贝: 

  • 深拷贝会复制对象的所有属性,包括嵌套的引用类型数据。
  • 对于基本数据类型,深拷贝同样复制其值
  • 对于引用类型,深拷贝会创建一个新的对象,并递归地复制原始对象中引用类型数据的所有属性,从而在内存中创建一个全新的副本
  • 这意味着原始对象和拷贝对象在内存中是完全独立的,修改拷贝对象不会影响原始对象。

对比:

  • 内存独立性:深拷贝产生的对象在内存中是完全独立的,而浅拷贝产生的对象在引用类型数据上与原始对象共享内存。
  • 修改影响:修改深拷贝对象的属性不会影响原始对象,而修改浅拷贝对象的引用类型属性会影响原始对象。
  • 性能开销:深拷贝通常比浅拷贝更耗时,因为它需要递归复制所有嵌套的对象。
  • 适用场景:如果需要完全独立的数据副本,应该使用深拷贝;如果只需要复制顶层属性,或者原始对象不会改变,可以使用浅拷贝。 

案例:栈的深拷贝 

Stack(const Stack& st)
{_array = (DataType*)malloc(sizeof(DataType*) * st._capacity);if (NULL == _array){perror("malloc申请空间失败");return;}memcpy(_array, st._array, sizeof(DataType) * st._size);_size = st._size;_capacity = st._capacity;
}

4.类中如果没有涉及资源申请,拷贝构造函数是否写都可以;但是一旦涉及到资源申请,拷贝构造函数是一定要写的,否则就是浅拷贝

3.拷贝构造函数典型调用场景

  • 使用已存在对象创建新对象
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象

 综合案例分析

#include<iostream>
using namespace std;
class Date
{
public://构造函数Date(int year, int minute, int day){cout << "Date(int,int,int):" << this << endl;}//拷贝构造函数Date(const Date& d){cout << "Date(const Date& d):" << this << endl;}//析构函数~Date(){cout << "~Date():" << this << endl;}private:int _year;int _month;int _day;
};Date Test(Date d)
{Date temp(d);return temp;
}int main()
{Date d1(2024, 6, 25);Test(d1);return 0;
}

由以上案例可以看出,传值传参会调用拷贝构造,所以为了提高程序的效率,返回时根据实际场景,能用引用尽量使用引用 

4.总结

  • 如果没有管理资源,一般情况下就不需要写拷贝构造,默认生成的拷贝构造就可以,比如日期类
  • 如果都是自定义类型成员,内置类型成员没有指向资源,也是使用默认生成的拷贝构造即可,如MyQueue
  • 一般情况下,不需要显式写析构,就不用写拷贝构造
  • 如果内部有指针或一些值指向资源,需要显式写析构,通常就需要显式写构造完成深拷贝,如:Stack,Queue,List 

拷贝构造函数也比较抽象,希望大家看完本文有所收获

点赞收藏关注是博主不断更新优质好文的动力哦~  

 

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

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

相关文章

《梦醒蝶飞:释放Excel函数与公式的力量》 5.2VLOOKUP函数

第二节 5.2VLOOKUP函数 HLOOKUP函数&#xff1a;水平查找的能手&#xff0c;在Excel中&#xff0c;HLOOKUP函数&#xff08;Horizontal Lookup的缩写&#xff09;是执行水平查找的函数&#xff0c;它允许你根据一个关键值在表格的第一行中查找&#xff0c;并返回同一列中另一个…

模组硬件通用丨模组USB电路设计指南

USB&#xff08;全称&#xff1a;Universal Serial Bus&#xff09;是一种串口总线标准&#xff0c;也是一种输入输出接口的技术规范&#xff0c;广泛应用于个人电脑和移动设备等信息通讯产品&#xff0c;并扩展至摄影器材、数字电视&#xff08;机顶盒&#xff09;、游戏机等相…

本地可以Run大模型吗?Llama3?安排!

➡️ 前言 本地可以跑大模型吗? ChatGPT发布之后&#xff0c;引起了AI领域剧烈震动&#xff0c;从2023年3月百度发布新一代大预言模型文心一言开始&#xff0c;大模型如雨后春笋般不断涌现&#xff0c;国内阿里巴巴的通义千问、华为的盘古大模型、科大讯飞的星火认知大模型、…

木材容易发霉怎么办除霉处理方法

木材存放不当就容易出现发霉情况&#xff0c;那么可通过那些方法将木材表面的霉斑除掉呢&#xff1f;经ihaoer防霉人士介绍处理木材发霉处理方法如下&#xff1a; 木材发霉的原因主要包括木材本身的营养物质、环境湿度、温度以及空气流动性等因素。木材中含有蛋白质、淀粉、油类…

CPR曲面重建代码

废话不说&#xff0c;直接上代码&#xff1a; #include "vtkAutoInit.h" #include "vtkPolyData.h" #include "vtkProbeFilter.h" #include "vtkParametricFunctionSource.h" #include "vtkParametricSpline.h" #include &…

基于Java微信小程序校园自助打印系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…

【开源项目】智慧北京案例~超经典实景三维数字孪生智慧城市CIM/BIM数字孪生可视化项目——开源工程及源码!

飞渡科技数字孪生北京管理平台&#xff0c; 依托实景数字孪生底座&#xff0c;以城市感知网络为硬件基础&#xff0c;以城市大数据为核心资源&#xff0c;以数字孪生、云计算、人工智能为关键技术&#xff0c;实现城市产业规划、资产安全管理、城市能耗监控等一体化空间融合。 …

基于电商模式的性能测试(2) —— 使用Jmeter参数化功能+JSR223 PreProcessor+JSON Extractor完成注册登录的数据驱动

1、前置条件 此例使用的是GitHub上一个开源的电商项目mall&#xff0c;需要的可以去GitHub上下载部署&#xff0c;有详细的部署教程&#xff1a; GitHub地址&#xff1a;github.com/macrozheng/…部署教程&#xff1a;macrozheng.github.io/mall-learni… 2、场景抽离 首先要…

C#的无边框窗体项目模板 - 开源研究系列文章

继续整理和编写代码及博文。 这次将笔者自己整理的C#的无边框窗体项目的基本模板进行总结&#xff0c;得出了基于C#的.net framework的Winform的4个项目模板&#xff0c;这些模板具有基本的功能&#xff0c;即已经初步将代码写了&#xff0c;直接在其基础上添加业务代码即可&am…

java实现一个图的最短路径算法

import java.util.*; //java实现一个图的最短路径算法 public class Test_34 { // 定义一个常量INF&#xff0c;表示无穷大。private static final int INF Integer.MAX_VALUE; // 定义一个方法dijkstra&#xff0c;接受一个二维数组图和一个起始节点作为参数。public s…

七牛云 Miku 快直播,陪你一起看球!

足球&#xff0c;作为全球最受欢迎的运动之一&#xff0c;每一次大赛都是球迷心中的狂欢&#xff0c;每一场比赛都记录着足球历史的精彩。 2000 年&#xff0c;特雷泽盖的金球&#xff0c;照亮了法兰西的足球梦想。 2004 年&#xff0c;查理斯特亚斯的头槌破门&#xff0c;成就…

浅谈逻辑控制器之while控制器

浅谈逻辑控制器之while控制器 “While控制器”是一种高级控制结构&#xff0c;它允许用户基于特定条件来循环执行其下的子采样器或控制器&#xff0c;直至该条件不再满足。本文旨在详细介绍While控制器的功能、配置方法、使用场景以及实践示例&#xff0c;帮助测试工程师高效利…

工信部中小企业局一行莅临盘古信息调研指导

近日&#xff0c;中小企业数字化转型城市试点调研交流活动在广东东莞举行&#xff0c;工业和信息化部中小企业局副局长商超&#xff0c;广东工业和信息化厅二级巡视员张振祥&#xff0c;工业和信息化部中小企业局创业创新处处长李海涛&#xff0c;东莞市委常委、副市长刘光滨&a…

泵设备的监测控制和智慧运维

泵是一种输送流体或使流体增压的机械。它通过各种工作原理&#xff08;如离心、柱塞等&#xff09;将机械能转换为流体的动能或压力能&#xff0c;从而实现液体的输送、提升、循环等操作。 泵的一些具体应用场景&#xff1a; 1.智能水务&#xff1a;在城市供水管网中&#xff…

python turtle 002代码表白

代码&#xff1a;pythonturtle002表白资源-CSDN文库 # 作者V w1933423 import turtle import mathdef draw_love():# 创建turtle画笔t turtle.pen()t turtle# 提起画笔&#xff0c;移动到起始位置t.up()t.goto(0, 150)t.down()# 设置颜色并开始填充t.color(red)t.begin_fill…

​中国9大流域地图SHP数据

九大流域片区是指中国境内九个主要流域片区。 分别包括东南诸河区、内陆河区、松辽河流区、海河流域区、淮河流域区、珠江流域片、西南诸河片、长江流域片和黄河流域片等。 如果这九大流域数据对你有用&#xff0c;请在文末查看该数据的领取方法。 中国9大流域图 流域&…

jeecg启动微服务并注册到本地nacos

1、maven勾选环境和微服务模式&#xff0c;并刷新 2、pom文件修改nacos注册地址 3、本地启nacos gateway 和自己想要的cloud下面的模块pos sys 4、打断点测试接口&#xff0c;访问gateway端口和想要测试的地址

【数据结构】线性表之《队列》超详细实现

队列 一.队列的概念及结构二.顺序队列与链队列1.顺序队列2.链队列 三.链队列的实现1.创建队列2.初始化队列3.入队4.出队5.获取队头元素6.获取队尾元素7.队列的大小8.队列的判空9.清空队列10.销毁队列 四.队列的盲区五.模块化源代码1.Queue.h2.Queue.c3.test.c 六.栈和队列必做O…

unity-调用讯飞星火语音唤醒-新版windowsSDK

调用讯飞星火语音唤醒-新版windowsSDK 先贴一张在unity中 wins系统下成功调用新版的讯飞windowsSDK的运行截图 为什么要用讯飞的语音唤醒&#xff1f; 项目中需要在unity和win系统下进行语音唤醒开启语音对话&#xff0c;而语音唤醒比较成熟的方案大多都是在linux系统下的&…

kafka 生产者 API 实践总结

文章目录 前言创建 kafka 生产者同步与异步发送消息同步发送异步发送 生产者参数配置client.idacks消息传递时间 序列化器在Kafka中使用Avro记录 分区标头拦截器配额和节流 前言 kafka 对外提供的 API 主要有两类&#xff1a;生产者 API 和 消费者 API&#xff0c;本文将从Kaf…