【C++ | 拷贝构造函数】一文了解C++的 拷贝(复制)构造函数
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
⏰发布时间⏰:2024-06-07 21:05:34
本文未经允许,不得转发!!!
目录
- 🎄一、为什么需要 拷贝构造函数
- 🎄二、什么是 拷贝构造函数
- 🎄三、使用 拷贝构造函数
- 🎄四、默认的 拷贝构造函数
- 🎄五、总结

![]()
🎄一、为什么需要 拷贝构造函数
如果程序中出现需要 拷贝构造函数 的代码,而又没有提供拷贝构造函数时,系统会提供一个默认的拷贝构造函数,该函数只会完成浅拷贝而不会进行深拷贝,这就是为什么需要 拷贝构造函数 的原因。
关于浅拷贝、深拷贝的知识,可以看这篇文章:C++入门知识-拷贝构造函数-浅拷贝、深拷贝
下面用例子说明浅拷贝可能产生的问题:
// g++ 11_Copy_Constructor_Date.cpp
#include <iostream>
#include <stdio.h>using namespace std;class CDate
{
public:CDate(int year, int mon, int day); // 构造函数声明~CDate(); // 析构函数声明void show(){//cout << "Date: " << m_year << "." << m_mon << "." << m_day << endl;cout << "Date: " << str << endl;}private:int m_year;int m_mon;int m_day;char *str;
};// 构造函数定义
CDate::CDate(int year, int mon, int day)
{m_year = year;m_mon = mon;m_day = day;str = new char[64];sprintf(str, "%4d.%02d.%02d", year,mon,day);cout << "Calling Constructor" << ", this=" << this <<endl;
}// 析构函数定义
CDate::~CDate()
{cout << "Calling Destructor" << ", this=" << this <<endl;delete [] str;
}int main()
{CDate date_1(2024,06,05);CDate date_2 = date_1; // 调用拷贝构造函数date_1.show();date_2.show();return 0;
}
上面代码由于没有进行深拷贝,导致 double free 了的错误,因为浅拷贝只复制了str的值,在两个对象销毁时都delete了。

![]()
🎄二、什么是 拷贝构造函数
拷贝构造函数,有些书也把其成为复制构造函数,其作用是将一个对象复制到新创建的对象中。
类的拷贝构造函数原型通常是这样的:类名(const 类名 &);。以CDate类为例,其拷贝构造函数如下:
CDate(const CDate &);
拷贝构造函数的几个特点:
1、函数名和类名相同,因为它也是构造函数的一种;
2、第一个参数必须是一个自身类类型的引用,且其他参数都有默认值。
3、第一个参数必须是自身类类型的引用的原因:如果不上引用则需要拷贝它的实参,为了要拷贝实参,又需要调用拷贝构造函数,如此无限循环;
清楚了这些之后,我们修改一下上个小节的代码,添加一个拷贝构造函数:
// g++ 11_Copy_Constructor_Date.cpp
#include <iostream>
#include <stdio.h>using namespace std;class CDate
{
public:CDate(int year, int mon, int day); // 构造函数声明CDate(const CDate& date); // 拷贝构造函数声明~CDate(); // 析构函数声明void show(){//cout << "Date: " << m_year << "." << m_mon << "." << m_day << endl;cout << "Date: " << str << endl;}private:int m_year;int m_mon;int m_day;char *str;
};// 构造函数定义
CDate::CDate(int year, int mon, int day)
{m_year = year;m_mon = mon;m_day = day;str = new char[64];sprintf(str, "%4d.%02d.%02d", year,mon,day);cout << "Calling Constructor" << ", this=" << this <<endl;
}// 拷贝构造函数定义
CDate::CDate(const CDate& date)
{m_year = date.m_year;m_mon = date.m_mon;m_day = date.m_day;str = new char[64];sprintf(str, "%4d.%02d.%02d", m_year,m_mon,m_day);cout << "Calling Copy Constructor" << ", this=" << this <<endl;
}// 析构函数定义
CDate::~CDate()
{cout << "Calling Destructor" << ", this=" << this <<endl;delete [] str;
}int main()
{CDate date_1(2024,06,05);CDate date_2 = date_1; // 调用date_2的拷贝构造函数date_1.show();date_2.show();return 0;
}
运行结果如下,添加拷贝构造函数后,运行不会报错,因为拷贝构造函数中重新new了内存:

![]()
🎄三、使用 拷贝构造函数
为了使用 拷贝构造函数,我们必须清楚 拷贝构造函数 在什么情况下会被调用,然后再根据自己设计的类是否需要深拷贝来决定怎样定义该类的 拷贝构造函数。
会调用拷贝构造函数的几种情况:
- 使用同类型的对象去初始化另一个对象时。
如下代码,使用了 date_1 初始化 date_2:CDate date_1(2024,06,05); CDate date_2 = date_1; // 调用date_2的拷贝构造函数 - 将一个对象作为实参传递给一个非引用类型的形参。
void printDate(CDate date) {date.show(); } ... printDate(date_2); // 实参传值到形参,调用拷贝构造函数 - 从一个返冋类型为非引用类型的函数返回一个对象。
CDate g_date(2024,06,06);; CDate getDate() {return g_date; // 3、返回对象时,调用拷贝构造函数 }
下面例子演示了调用拷贝构造函数的这三种场景:
// g++ 11_Copy_Constructor_Date.cpp
#include <iostream>
#include <stdio.h>using namespace std;class CDate
{
public:CDate(int year, int mon, int day); // 构造函数声明CDate(const CDate& date); // 拷贝构造函数声明~CDate(); // 析构函数声明void show(){//cout << "Date: " << m_year << "." << m_mon << "." << m_day << endl;cout << "Date: " << str << endl;}private:int m_year;int m_mon;int m_day;char *str;
};// 构造函数定义
CDate::CDate(int year, int mon, int day)
{m_year = year;m_mon = mon;m_day = day;str = new char[64];sprintf(str, "%4d.%02d.%02d", year,mon,day);cout << "Calling Constructor" << ", this=" << this <<endl;
}// 拷贝构造函数定义
CDate::CDate(const CDate& date)
{m_year = date.m_year;m_mon = date.m_mon;m_day = date.m_day;str = new char[64];sprintf(str, "%4d.%02d.%02d", m_year,m_mon,m_day);cout << "Calling Copy Constructor" << ", this=" << this <<endl;
}// 析构函数定义
CDate::~CDate()
{cout << "Calling Destructor" << ", this=" << this <<endl;delete [] str;
}void printDate(CDate date)
{date.show();
}CDate g_date(2024,06,06);;
CDate getDate()
{return g_date; // 3、返回对象时,调用拷贝构造函数
}int main()
{CDate date_1(2024,06,05);CDate date_2 = date_1; // 1、调用date_2的拷贝构造函数date_1.show();date_2.show();cout << endl;printDate(date_2); // 2、实参传值到形参,调用拷贝构造函数cout << endl;getDate();cout << endl;return 0;
}
运行结果:

![]()
🎄四、默认的 拷贝构造函数
如果没有为一个类定义拷贝构造函数,则编译器会合成一个“默认拷贝构造函数”。
默认的拷贝构造函数会逐个复制非静态成员( 成员复制也称为浅复制)的值到正在创建的对象中。根据成员类型有下面几种情况:
1、如果成员是内置类型,则直接复制;
2、如果成员本身就是类对象,则将使用这个类的拷贝构造函数来复制类对象;
3、如果成员是数组,默认的拷贝构造函数会逐元素地拷贝一个数组类型的成员。
![]()
🎄五、总结
👉本文介绍C++的拷贝构造函数,为什么需要拷贝构造函数,什么是拷贝构造函数,怎么使用拷贝构造函数,默认拷贝构造函数。

如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁
相关文章:
【C++ | 拷贝构造函数】一文了解C++的 拷贝(复制)构造函数
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 ⏰发布时间⏰:2024-06-07 2…...
【工具】Vmware17 安装mac(13.6.7)虚拟机
目录 0.简介 1.环境 2.详细步骤 2.1下载mac镜像(可以选择你所需要的) 2.2 VMware安装 1)创建新的虚拟机 2)选择【典型】,点击下一步 3)选择【安装程序光盘映像文件】,点击浏览ÿ…...
mac node版本切换 nvm install nvm ls-remote N/A问题
mac 使用nvm 切换node版本失败或者 nvm install &nvm ls-remote N/A问题 一、出现情况 输入 nvm install v16.18.0输出结果 Version 16.18.0 not found try nvm is-remote•to browse available versions.输入 nvm ls-remote输出结果 N/A二、原因分析 1. 镜像包获取…...
牛客小白月赛95
vp,为后面的比赛做准备 A.相遇 #include <iostream> #include <vector> #include <algorithm> #include <set> #include <unordered_map> #include <cstring> #include <cstdio> #include <string> #include <…...
Python实现调用并执行Linux系统命令
😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 🤓 同时欢迎大家关注其他专栏,我将分享Web前后端开发、人工智能、机器学习、深…...
古字画3d立体在线数字展览馆更高效便捷
在数字时代的浪潮中,大连图书馆以崭新的面貌跃然屏幕之上——3D全景图书馆。这座承载着城市文化精髓与丰富知识资源的数字图书馆,利用前沿的三维建模技术,为我们呈现了一个全新的知识世界。 随时随地,无论您身处何地,只…...
编写程序,提示用户输入以米/秒(m/s)为单位的速度v和以米/秒的平方(m/s)为单位的加速度 a,然后显示最短跑道长度。
(物理:求出跑道长度)假设一个飞机的加速度是a而起飞速度是v,那么可以使用下 面的公式计算出飞机起飞所需的最短跑道长度: 编写程序,提示用户输入以米/秒(m/s)为单位的速度v和以米/秒的平方(m/s)为单 位的加速度 a,然后显示最短跑道长度。下面…...
k8s 对外发布(ingress)
在k8s中,service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制; 对集群外部,他类似负载均衡器,可以在集…...
FL Studio21.2.7最新中文破解版免费激活,音乐制作全掌握!
在数字音乐制作的海洋中,你是否曾因软件的复杂操作、高昂费用而望而却步?是否梦想拥有一款既强大又亲民的音乐制作工具,让你的创作激情不受束缚?今天,让我们一起探索FL Studio21——这款官方中文破解激活码及免费版下载…...
2 - 寻找用户推荐人(高频 SQL 50 题基础版)
2.寻找用户推荐人 考点: sql里面的不等于,不包含null -- null 用数字判断筛选不出来 select name from Customer where referee_id !2 OR referee_id IS NULL;...
高考志愿填报有哪些技巧和方法
一年一度高考季,又高考志愿填报的时侯了。高考志愿填报的时侯,需要考虑的因素比较多,有的同学觉是离家越远越好,要放飞自我,家长再也管不了我了。有的同学觉得专业比学校牌子重要,只要报个好专业࿰…...
codereview时通常需要关注哪些
在团队成员之间互相进行代码审查(codereview)时,通常可以从以下几个方面来确保代码的质量和可维护性: 代码结构和格式: 检查代码是否遵循了项目约定的编码规范和风格指南。确保代码具有良好的可读性,比如合…...
DSP28335模块配置模板系列——定时器中断配置模板
一、配置步骤: 1.使能定时器时钟 EALLOW;SysCtrlRegs.PCLKCR3.bit.CPUTIMER2ENCLK 1; // CPU Timer 2EDIS; 2.设置定时器的中断向量 EALLOW;PieVectTable.TINT2 &TIM2_IRQn;EDIS;其中TIM2_IRQn时定时器中断服务程序的名称 ,将中断服务函数的地址…...
使用 Apache Commons Exec 自动化脚本执行实现 MySQL 数据库备份
😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…...
【中间件系列】浅析redis是否适合做消息队列
文章目录 一、简单的list消息队列1.命令示例2.伪代码示例3.方案优劣 二、Pub/Sub发布订阅1.消息丢失2.消息堆积 三、相对成熟的Stream1.redis命令介绍2.多消费者组测试3.Stream会持久化吗?4.消息堆积如何解决? 总结 用redis也是比较久了,并且…...
[NOVATEK] NT96580行车记录仪功能学习笔记
一、u-Boot升级灯 运行u-Boot程序时LED灯闪烁,找到运行过程中一直在运行的函数在里面进行LED引脚电平的翻转 宏定义 Z:\SunFan\AHD580\pip\na51055_PIP\BSP\u-boot\include\configs\nvt-na51055-evb.h Z:\SunFan\AHD580\pip\na51055_PIP\BSP\u-boot\drivers\mtd\nvt_flash_…...
创新案例 | AI数据驱动下的全域数字化转型的五大关键洞见
近年来通过全域数字化转型在竞争激烈的市场中脱颖而出。传统零食行业面临市场竞争加剧和消费者需求多样化的挑战,如何利用数据驱动和AI技术,能更好地实现会员运营效率和用户满意度的显著提升呢?本文将探讨全域数字化转型的五大关键洞见&#…...
学习笔记——网络参考模型——TCP/IP模型(网络层)
三、TCP/IP模型-网络层 1、IPV4报头 (1)IPV4报文格式 IP Packet(IP数据包),其包头主要内容如下∶ Version版本∶4 bit,4∶表示为IPv4; 6∶表示为IPv6。 Header Length首部长度∶4 bit,代表IP报头的长度(首部长度),如果不带Opt…...
AI初识--LLM、ollama、llama都是些个啥?
LLM全称(large language model)也就是大语言模型 什么是Ollama,它与Llama是什么关系? Ollama是一个开源的 LLM(大型语言模型)服务工具,用于简化在本地运行大语言模型,降低使用大语…...
【全开源】JAVA打车小程序APP打车顺风车滴滴车跑腿源码微信小程序打车源码
:构建便捷出行新体验 一、引言:探索打车系统小程序源码的重要性 在数字化快速发展的今天,打车系统小程序已成为我们日常生活中不可或缺的一部分。它以其便捷、高效的特点,极大地改变了我们的出行方式。而背后的关键,…...
3KW无线充电系统设计:开环控制与闭环控制的MATLAB Simulink仿真模型,采用双边L...
3KW无线充电系统设计(MATLAB simulink仿真模型) 控制方式:开环控制闭环控制 拓扑结构:双边LCC拓扑结构 输入电压:750V 输出电压:400V 传输功率:3KW 最近在折腾一个3KW无线充电系统的仿真项目&am…...
新手指南:掌握3MF格式实现Blender高效3D打印工作流
新手指南:掌握3MF格式实现Blender高效3D打印工作流 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 副标题:从格式解析到自动化处理的完整应用方案…...
FanControl深度应用指南:从噪音溯源到智能散热系统搭建
FanControl深度应用指南:从噪音溯源到智能散热系统搭建 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/f…...
Vivado仿真踩坑实录:PR模式不支持仿真的快速解决方案(附详细步骤)
Vivado仿真避坑指南:PR模式不支持仿真的深度解析与实战方案 刚接触FPGA开发的朋友们,不知道你们是否遇到过这样的场景:在Vivado中精心设计了一个工程,准备进行仿真验证时,突然弹出一个令人困惑的错误提示——"Sim…...
答辩 PPT 不用熬!PaperXie AI PPT 让毕业论文答辩赢在 “门面”
paperxie-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/AIPPThttps://www.paperxie.cn/ppt/createhttps://www.paperxie.cn/ppt/create 又到毕业冲刺季,当论文终于敲下最后一个句号,毕业论文答辩 PPT却成了新的 “熬夜重灾区”:…...
Windows 11 下 3D Gaussian Splatting (3DGS) 环境配置与实战指南
1. Windows 11下的3DGS环境搭建全攻略 第一次接触3D Gaussian Splatting(简称3DGS)这个技术时,我完全被它惊艳到了。它能够从几张普通的照片重建出逼真的3D场景,而且渲染速度极快。不过说实话,在Windows 11上配置这个环…...
从智慧灯杆到无人驾驶:如何用Raspberry Pi 4和Arduino搭建微型智慧城市实验平台
从智慧灯杆到无人驾驶:如何用Raspberry Pi 4和Arduino搭建微型智慧城市实验平台 在创客文化和高校工程教育中,低成本硬件的创新应用正掀起一场微型智慧城市实验的革命。只需一块树莓派主板、几个传感器和开源软件,就能在桌面上复现价值数百万…...
Ubuntu 24.04镜像源配置全攻略:从原理到实战(含常见报错解决)
Ubuntu 24.04镜像源深度解析与高效配置实战 最近在帮朋友配置新装的Ubuntu 24.04时,发现这个版本在软件源管理上做了重大调整——从传统的sources.list文件变成了结构化更强的sources.d目录配置方式。这个变化让不少习惯了旧版本的用户感到困惑,也让我意…...
猫抓插件:让网页资源捕获变得高效简单的浏览器扩展解决方案
猫抓插件:让网页资源捕获变得高效简单的浏览器扩展解决方案 【免费下载链接】cat-catch 猫抓 chrome资源嗅探扩展 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 在数字时代,我们每天浏览网页时都会遇到各种有价值的媒体资源——可…...
计算机毕业设计springboot校园文化社区视频网站 基于SpringBoot的校园文化交流短视频平台 SpringBoot框架下的高校文化分享与视频互动系统
计算机毕业设计springboot校园文化社区视频网站94nso9 (配套有源码 程序 mysql数据库 论文)本套源码可以先看具体功能演示视频领取,文末有联xi 可分享在"互联网校园"理念全面渗透的今天,视频已成为大学生记录生活、传播…...
