C++类和对象 ——构造函数
C++拷贝构造函数详解
- 什么是拷贝构造函数?
- 拷贝构造函数的特征
- 默认拷贝构造函数
- 为什么需要显示定义构造函数?
- 拷贝构造函数的调用场景
- 什么时候不需要自己定义拷贝构造函数
什么是拷贝构造函数?
在现实生活中,拷贝构造函数就好像我们上学时候干的一件事——抄作业(doge,但在现实生活中,这是件不好的事,但是在类和对象中,拷贝构造函数确是一个作用极大的东西。
在创建对象时,能否船创建一个与已经存在对象一模一样的对象呢?当然可以,这时候就要使用拷贝构造函数了。
拷贝构造函数: 只有单个形参,该形参是对 本类类型对象的引用(一般常用const修饰),在用 已存在的类类型对象创建新对象时由编译器自动调用。
对于内置类型,就相当于int a = b,这样,用b来构造a
注意: 构造和赋值是两件不一样的事,看下面一段代码:
//拷贝构造
int b = 10;
int a = b;//赋值
int a = 10, b;
b = a;
拷贝构造函数的特征
拷贝构造函数也是特殊的成员函数之一:
- 拷贝构造函数是构造函数的一个重载形式
- 拷贝构造函数的参数只有一个且必须是类对象的引用,使用传值方法编译器会强制检查报错,因为会引发无穷递归问题。
相信这里大家一定会有疑惑,为什么传值的方法会引发无穷递归的问题?
看下面一段代码:
#include<iostream>
class Date
{
private:int _year;int _month;int _day;
public:Date(int year = 1970, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){std::cout << "Date(const Date& d)" << std::endl;_year = d._year;_month = d._month;_day = d._day;}
}void func(Date d)
{}int main()
{Date d1(2023,5,1);func(d1);return 0;
}
上面这段代码的运行结果如下:

这说明了什么问题?
我们使用了拷贝构造函数,可是在哪里使用的呢?从代码上看,并没有看到我们使用了拷贝构造啊?
这里就涉及到一个经典的问题了,还记得形参和实参之间的关系吗?没错,就是她俩在搞鬼!!
- 形参是实参的临时拷贝!!!
- 形参是实参的临时拷贝!!!
- 形参是实参的临时拷贝!!!
重要的事情说三遍,没错!正是因为这个性质,在调用func函数时,我们将d1传给形参d,就发生了用d1来拷贝复制形参的出现,那么有了这一个理解,我们就能了解为什么在设计拷贝构造函数的时候不能使用传值调用了。
因为如果用传值调用,效率不高是一个,另外一个就是调用拷贝复制函数时,形参和实参之间的复制需要一直调用拷贝构造,就会出现无限递归的情况,具体看下图:

因此,现在的编译器为了避免这种无限递归的产生,会对复制构造函数传值的设计进行强制的检查,一旦我们用传值的方式设计拷贝构造函数,将无法完成编译。
默认拷贝构造函数
若未显示定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象对内置类型是按照字节方式直接拷贝的(这种拷贝又叫做浅拷贝,或者叫值拷贝),而对自定义类型是调用其拷贝构造函数来完成拷贝的。
在前面日期类的基础上,我们再创建一个类,来测试一下这个特性。
#include<iostream>
class Date
{
private:int _year;int _month;int _day;
public:Date(int year = 1970, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){std::cout << "Date(const Date& d)" << std::endl;_year = d._year;_month = d._month;_day = d._day;}
};
class Time
{
private:int hour;int min;int second;Date x;
};int main()
{Time d1;Time d2(d1);return 0;
}

可以看到,我们并没有定义Time类的拷贝构造,所以使用的是系统自动生成的默认拷贝构造函数,而从运行结果看其确实符合上诉所说的特性。
为什么需要显示定义构造函数?
大家刚接触到拷贝构造函数的时候一定有一个问题,竟然编译器生成的拷贝构造函数已经可以完成字节序的值拷贝了,那还需要显示定义吗?也许对日期类这种比较简单的类不需要,那如果是更复杂的一些类呢?看下面的例子:
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;}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;
}
上面这段代码在运行之后将会崩溃,为什么呢?我们首先来看看定义的两个stack对象里保存的东西:

两个对象动态申请的数组指向同一块空间,这就是默认拷贝构造函数带来的后果,而如此造成的结果并不是我们想要的,在程序结束调用析构的时候,将会对同一块空间释放两次,因此会造成错误。
因此,类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构 造函数是一定要写的,否则就是浅拷贝。
拷贝构造函数的调用场景
- 使用已存在对象创建新对象
- 函数参数为类类型对象(形参的拷贝创建)
- 函数返回值类型为类类型对象(创建临时变量)
什么时候不需要自己定义拷贝构造函数
- 类成员都是自定义类型
- 所有的成员都只需要浅拷贝就能完成任务
好了,以上就是这篇博客的全部内容,如果大伙发现博主哪里写的有问题或者有疑惑的话,欢迎评论区指出!😘
相关文章:
C++类和对象 ——构造函数
C拷贝构造函数详解 什么是拷贝构造函数?拷贝构造函数的特征默认拷贝构造函数为什么需要显示定义构造函数?拷贝构造函数的调用场景什么时候不需要自己定义拷贝构造函数 什么是拷贝构造函数? 在现实生活中,拷贝构造函数就好像我们上…...
第2章-分治法
第2章-分治法 总分:100分 得分:20.0分 1 . 多选题 中等 10分 有关以下代码,说法正确的是( ABCE) def BinarySearch(s, x, low, high):if (low > high):return -1middle (low high) / 2if (x s[mid…...
20天能拿下PMP吗?
新版大纲,专注于人员、过程、业务环境三个领域,内容贯穿价值交付范围(包括预测、敏捷和混合的方法)。除了考试时间由240分钟变更为230分钟、200道单选题变为180道(包含单选和多选)之外,新考纲还…...
Word处理控件Aspose.Words功能演示:在 Java 中将 Word DOC/DOCX 转换为 PDF
Aspose.Words是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。 Aspose API支持流行文件格式处理,并…...
数据安全的重要性
数据安全非常重要,因为我们生活在数字化时代,许多信息和数据都以数字形式存储和传输。如果这些数据受到未经授权的访问、篡改、泄露或破坏,会对个人、组织和国家造成严重的损失。 以下是数据安全的重要性: 1. 保护各类隐私&#x…...
要创建富文本内容?Kendo UI Angular组件有专门的编辑器应对!
您的Angular应用程序可能需要允许用户添加带有格式化选项的文本、图像、表格、外观样式和/或链接,使用Kendo UI for Angular的编辑器,可以轻松搞定这些! Kendo UI for Angular是专业级的Angular UI组件库,不仅是将其他供应商提供…...
工赋开发者社区 | 装备制造企业数字化转型总体框架
导读 当前,面对技术、市场以及供应链等多重挑战,在软件定义、数据驱动、数字孪生、大数据、人工智能及元宇宙等技术加持下,装备制造企业不断采用新工艺、新材料,以新模式推动产品快速创新。企业积极关注并探索数字化转型路径&…...
Python趋势外推预测模型实验完整版
趋势外推预测模型实验完整版 实验目的 通过趋势外推预测模型(佩尔预测模型),掌握预测模型的建立和应用方法,了解趋势外推预测模型(佩尔预测模型)的基本原理 实验内容 趋势外推预测模型 实验步骤和过程…...
KALI入门到高级【第三章】
预计更新第一章 入门 1.1 什么是Kali Linux? 1.2 安装Kali Linux 1.3 Kali Linux桌面环境介绍 1.4 基本命令和工具 第二章 信息收集 1.1 网络扫描 1.2 端口扫描 1.3 漏洞扫描 1.4 社交工程学 第三章 攻击和渗透测试 1.1 密码破解 1.2 暴力破解 1.3 漏洞利用 1.4 特…...
React Native中防止滑动过程中误触
React Native中防止滑动过程中误触 在使用React Native开发的时,当我们快速滑动应用的时候,可能会出现误触,导致我们会点击到页面中的某一些点击事件,误触导致页面元素响应从而进行其他操作,表现出非常不好的用户体验。 一、问题…...
【c语言】函数递归调用
创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!! 主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步! 给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ…...
SPSS如何进行判别分析之案例实训?
文章目录 0.引言1.一般判别分析2.逐步判别分析3.决策树分析 0.引言 因科研等多场景需要进行绘图处理,笔者对SPSS进行了学习,本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结,本文对判别分析进行阐述。 1…...
Windows 10 字体模糊发虚的问题及解决方法
Windows 10字体模糊发虚! 如何解决?Windows 10是一款常见的操作系统,它拥有各种各样的功能,但是有些用户发现,在使用Windows 10时,字体会变得模糊发虚,这给用户带来了很多不便。下面,我们就来看看如何解决…...
渔人杯部分wp
文章目录 渔人杯神仙姐姐阿拉丁飘啊飘 渔人杯 神仙姐姐 点击拜 ,抓包发现get请求了/sx.php 返回如下 {"code":0,"num":1,"flag":"ctfsh0w-f1ag-n0t-h3r3-th1s-msg-just-a-j0ke-}{"}在repeater重复请求,发现…...
测试用例覆盖不全面的解决方法
测试用例覆盖不全面的解决方法 问题分析 在测试用例设计过程中,容易出现思维受限或者需求盲区,我们不可能完全覆盖用户使用的所有场景,编写测试用例的时不可能把所有的场景都能想周全,把所有的场景下的情况都写成测试用例去模拟、…...
AWS Lambda - 第一部分
Hello大家好,我们今天开始讨论AWS Lambda的内容。 SAP认证考试会涉及到很多Lambda的内容,想要通过认证考试虽然不一定非要精通开发,但需要知道Lambda的一些功能和特性、适用场景以及Lambda是如何工作的。 我们开始吧! Lambda与…...
Java 基础进阶篇(七)—— 面向对象三大特征之三:多态
文章目录 一、多态的概述二、多态中成员访问特点 ★三、多态的优势与劣势四、多态下的类型转换4.2 自动类型转换(从子到父)4.2 强制类型转换(从父到子)4.3 instanceof 关键字 一、多态的概述 多态:是指执行同一个行为…...
day9 实现UDP通信
目录 socket函数拓展 UDP通信实现过程 代码实现 socket函数拓展 send与recv函数: /*用于发送数据*/ ssize_t send(int sockfd, const void *buf, size_t len,int flags);/*用于接收数据*/ ssize_t recv(int sockfd, void *buf, size_t len,int flags);/*前三个…...
自然语言处理(NLP)在放射学报告评价中的应用:应用和技术进展
自然语言处理(NLP)在放射学报告评价中的应用:应用和技术进展 写在最前面摘要引言先进的技术BERT算法优点 Applications in Radiology 放射学应用Quality 质量将关键发现通知转诊临床医生放射科关键绩效指标和评估 个别放射科医生的表现同行学…...
日常开发为什么需要做Code Review
日常开发为什么需要做Code Review 一、背景 最近在开始一个新的项目,在查看项目中代码及具体细节时,发现这个项目真实一堆乱麻,没有规律可循,可总结下这个项目的缺陷 没有规律可循,没有结构性设计不做公共封装&#…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
