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

【C++】类和对象之拷贝构造函数篇

个人主页 : zxctscl
文章封面来自:艺术家–贤海林
如有转载请先通知

文章目录

  • 1. 前言
  • 2. 传值传参和传引用传参
  • 3. 概念
  • 4. 特征

1. 前言

在前面学习了6个默认成员函数中的构造函数和析构函数 【C++】构造函数和析构函数详解,接下来继续往后看拷贝构造函数。

拷贝构造函数就是用一个同类型的其他对象来构造。
要学习拷贝构造函数,得先了解传值传参和传引用传参。

2. 传值传参和传引用传参

class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(Date& d){_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:// 内置类型int _year;int _month;int _day;
};
void func1(Date d)
{}
void func2(Date& rd)
{}
int main()
{Date d1(2024, 2, 24);func1(d1);func2(d1);return 0;
}

C++规定自定义类型都会调用拷贝构造。
在这里插入图片描述
所以func2(d1);rd是d1的别名,直接完成调用了,不存在再有一个函数来传值传参。
在这里插入图片描述
在这里插入图片描述
来看看不传引用会怎么样

class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(Date d){_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 2, 24);Date d2(d1);return 0;
}

在这里插入图片描述
调用拷贝构造,要先传参,这里是传值,传参,会形成一个新的拷贝构造,进不来这个函数,一直递归下去。使用传值传参就不行。

3. 概念

在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。

在这里插入图片描述
那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

4. 特征

拷贝构造函数也是特殊的成员函数,其特征如下:

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

有时候可能会发生修改对象,为了保护对象,就可以在它前面加上const
是一种权限的缩小。

像下面的场景就能被检查出来:
在这里插入图片描述
就只能这样写:
在这里插入图片描述
在这里插入图片描述

  1. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内置类型成员内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

像下面的代码中就没有拷贝构造:

class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:// 内置类型int _year;int _month;int _day;};int main()
{Date d1(2024, 2, 24);Date d2(d1);d1.Print();d2.Print();return 0;
}

在这里插入图片描述

class Time
{
public:~Time(){cout << "~Time()" << endl;}// 强制编译器生成Time() = default;Time(const Time& t){cout << "Time(const Time& t)" << endl;_hour = t._hour;_minute = t._minute;_second = t._second;}private:int _hour;int _minute;int _second;
};class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:// 内置类型int _year;int _month;int _day;//自定义类型Time _t;};int main()
{Date d1(2024, 2, 24);Date d2(d1);d1.Print();d2.Print();return 0;
}

在这里插入图片描述
在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定
义类型是调用其拷贝构造函数完成拷贝的。

在这里插入图片描述

  1. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}// Stack st2(st1);Stack(const Stack& s){DataType* tmp = (DataType*)malloc(s._capacity *(sizeof(DataType)));if (tmp == nullptr){perror("malloc fail");exit(-1);}memcpy(tmp, s._array, sizeof(DataType) * s._size);_array = tmp;_size = s._size;_capacity = s._capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}

在这里插入图片描述
看这里s1和s2置空,s1置空不影响s2置空,他们是两个对象。但他们的地址指向同一个空间,同一个空间不能释放两次。会导致野指针。
在这里插入图片描述
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。
在这里插入图片描述

  1. 拷贝构造函数典型调用场景:
    使用已存在对象创建新对象
    函数参数类型为类类型对象
    函数返回值类型为类类型对象
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(2022, 1, 13);Test(d1);return 0;
}

在这里插入图片描述
为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。

有问题请指出,大家一起进步!!!

相关文章:

【C++】类和对象之拷贝构造函数篇

个人主页 &#xff1a; zxctscl 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 传值传参和传引用传参3. 概念4. 特征 1. 前言 在前面学习了6个默认成员函数中的构造函数和析构函数 【C】构造函数和析构函数详解&#xff0c;接下来继续往后看拷…...

Mybatisplus 传参参数为自定义sql, 使用条件构造器作为参数

1 pom依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version> </dependency> 2 mapper 接口文件 List<TBookOrder> searchDiy(Param(Const…...

C#与VisionPro联合开发——TCP/IP通信

TCP/IP&#xff08;传输控制协议/互联网协议&#xff09;是一组用于在网络上进行通信的通信协议。它是互联网和许多局域网的基础&#xff0c;为计算机之间的数据传输提供了可靠性、有序性和错误检测。在软件开发中&#xff0c;TCP/IP 通信通常用于实现网络应用程序之间的数据交…...

spring Boot快速入门

快速入门为主主要届介绍java web接口API的编写 java编辑器首选IntelliJ IDEA 官方链接&#xff1a;https://www.jetbrains.com/idea/ IEDA 前言 实例项目主要是web端API接口的使用&#xff0c;项目使用mysql数据库&#xff0c;把从数据库中的数据的查询出来后通过接口json数…...

FPGA SERDESE2 (SDR收发仿真)

高速 Serdes 环路测试 高速串行通信优势非常巨大,只需要很少的IO引脚就可以实现高速通信,这也是当今FPGA高速接口的核心 技术。比如XILINX的7代FPGA,GTX可以达到10.3125Gbps,ultrascale FPGA的GTH可以达到16Gbps。目前国产FPGA还难以达到这么高的接口速度。 高速串行通信经…...

Java异常体系结构核心解析-Throwable

资料不在于多&#xff0c;而在于精。好资料、好书&#xff0c;我们站在巨人的肩膀上前行&#xff0c;可以少走很多弯路。 通过搜索引擎找到自己需要的最好最权威信息&#xff0c;是一种很重要的能力。 Java源代码和官方资料Java™ Tutorials Java异常体系结构&#xff0c;是一种…...

Android MediaRecorder 相关

Android MediaRecorder 相关 本篇文章主要介绍下MediaRecorder类. 1:创建对象 MediaRecorder mediaRecordernew MediaRecorder();MediaRecorder可以直接通过无参构造直接创建对象. 2: 音频源 通过调用setAudioSource(int audio_source)来设置音频源,可以是麦克风.音频文件…...

Spring中关于事务的一些方方面面

事务隔离级别&#xff1a; 先了解一些事务隔离级别有哪些&#xff1a; 未提交读(Read Uncommitted)&#xff1a; 允许脏读&#xff0c;也就是可能读取到其他会话中未提交事务修改的数据 提交读(Read Committed)&#xff1a; 只能读取到已经提交的数据。Oracle等多数数据库默…...

LiveQing视频点播流媒体RTMP推流服务功能-支持配置开启 HTTPS 服务什么时候需要开启HTTPS服务

LiveQing视频点播流媒体RTMP推流服务功能支持配置开启 HTTPS 服务什么时候需要开启HTTPS服务 1、配置开启HTTPS1.1、准备https证书1.1.1、选择Nginx类型证书下载 1.2、配置 开启 HTTPS1.2.1 web页面配置1.2.2 配置文件配置 2、验证HTTPS服务3、为什么要开启HTTPS3.1、安全性要求…...

LabVIEW串口通信的激光器模块智能控制

LabVIEW串口通信的激光器模块智能控制 介绍了通过于LabVIEW的VISA串口通信技术在激光器模块控制中的应用。通过研究VISA串口通信的方法和流程&#xff0c;实现了对激光器模块的有效控制&#xff0c;解决了数据发送格式的匹配问题&#xff0c;为激光器模块的智能控制提供了一种…...

全球最受欢迎的DAWFL Studio 21.2.3.4004 中文破解版强悍来袭

1997年是一个「古老」的年代&#xff0c;那时人们还在用「猫」上网&#xff0c;微信、QQ的江湖被ICQ统治&#xff0c;音乐编辑领域 Cool Edit 如日中天。这一年 &#xff0c;FL Studio 的前身 FruityLoops 在比利时问世&#xff0c;26年来&#xff0c;FL已成长为全球最受欢迎的…...

【uni-app】常用组件和 API

常用组件 uni-app 为开发者提供了一系列基础组件&#xff0c;类似 HTML 里的基础标签元素&#xff0c;但 uni-app 的组件与 HTML 不同&#xff0c;而是与小程序相同&#xff0c;更适合手机端使用。 虽然不推荐使用 HTML 标签&#xff0c;但实际上如果开发者写了div等标签&…...

基于springboot+vue的安康旅游网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…...

monaco脚本编辑器 在无界中使用 鼠标点击不到

背景A项目使用无界引入B项目 经排查&#xff0c;是B使用的的monaco脚本编辑器无法在A的无界框架中引入的问题。 经查询&#xff0c;需要修改monaco源码来使之能在无界中使用。 解决方案&#xff1a;https://github.com/Tencent/wujie/issues/205。 有三种解决方案&#xff1a; …...

react中修改state中的值无效?

// 初始化state state {personArr:[{name:张三,id:1},{name:李四,id:2},{name:王五,id:3}] }componentDidMount(){const newName 赵六const indexUpdate 1const newArr this.state.personArr.map((item,index)>{if(indexUpdate index){return {...item,name:newName}}e…...

在Node.js中如何实现用户身份验证和授权

当涉及到构建安全的应用程序时&#xff0c;用户身份验证和授权是至关重要的一环。在Node.js中&#xff0c;我们可以利用一些流行的库和技术来实现这些功能&#xff0c;确保我们的应用程序具有所需的安全性。本篇博客将介绍如何在Node.js中实现用户身份验证和授权。 用户身份验…...

QT day2 2.21

1.使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 代码&#xff1a; #include "mywidget.h" #include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(pa…...

说说设备像素、css像素、设备独立像素、dpr、ppi 之间的区别

文章目录 一、背景二、介绍CSS像素设备像素设备独立像素dprppi 三、总结参考文献 一、背景 在css中我们通常使用px作为单位&#xff0c;在PC浏览器中css的1个像素都是对应着电脑屏幕的1个物理像素 这会造成一种错觉&#xff0c;我们会认为css中的像素就是设备的物理像素 但实…...

文生视频Sora

Sora&#xff1a;scalable diffusion models with transformers 文生视频模型 Sora&#xff1a;视频生成模型60s&#xff0c;视频中体现一定的物理逻辑 时空patch&#xff0c;是Sora创新的核心。 Sora 到底是不是物理引擎甚至世界模型&#xff1f;数据驱动的物理引擎 帆船在水里…...

汽车常识网:电脑主机如何算功率的计算方法?

今天汽车知识网就给大家讲解一下如何计算一台主机的功率。 它还会解释如何计算计算机主机所需的功率&#xff1f; &#xff1f; &#xff08;如何计算电脑主机所需的功率&#xff09;进行说明。 如果它恰好解决了您现在面临的问题&#xff0c;请不要忘记关注本站。 让我们现在就…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

k8s从入门到放弃之HPA控制器

k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率&#xff08;或其他自定义指标&#xff09;来调整这些对象的规模&#xff0c;从而帮助应用程序在负…...