拷贝构造函数
文章目录
- 一、4. 拷贝构造函数
今天我们来学习拷贝构造函数。
一、4. 拷贝构造函数
如果⼀个构造函数的第⼀个参数是自身类型的引用,且任何额外的参数都有默认值,则此叫做拷贝构造函数,也就是说拷贝构造是⼀个特殊的构造函数。
它的形式是这样的:
#include<iostream>
using namespace std;
class Date
{
//拷贝构造函数
Date(const Date & d)
{_year = d._year;_month = d._month;_day = d._day;
}
private:int _year;int _month;int _day;
};
拷贝构造具有以下特点:
- 拷贝构造函数是构造函数的⼀个重载。
拷贝构造函数和普通构造函数一样,名字与类名相同,并且也是用于创建对象(用已存在的对象创建新对象)。它与其他构造函数的区别在于参数类型,它的参数是同类对象的引用。拷贝构造函数通过其特殊的参数类型(类对象的引用)与其他构造函数形成了重载关系。编译器可以根据调用时的参数情况(是普通参数还是类对象引用)来决定调用哪一个构造函数。
Date(int year = 1, 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;
}int main()
{
//既初始化了对象,又调用了拷贝构造Date d1();return 0;
}
- 拷贝构造函数的第⼀个参数必须是类类型对象的引用,使用传值方式编译器直接报错,因为语法逻辑上会引发无穷递归调用。 拷贝构造函数也可以多个参数,但是第⼀个参数必须是类类型对象的引用,后面的参数必须有缺省值。
Date &d 是为引用,目的是防止程序循环拷贝构造。如果为(Date d),则主程序Date d2(d1)时将d1拷贝赋值给了d,每次要调用烤贝构造函数之前要先传值传参,传值传参是一种烤贝,又形成一个新的拷贝构造,就形成了无穷递归。
const目的是为了保证被引用的对象不因拷贝的改变而改变。
#include<iostream>
using namespace std;
class Date
{ public:Date(int year = 1, 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;
}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 7, 5);Date d2(d1);d2.Print();return 0;
}
- C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成。
C++把类型分成内置类型(基本类型)和自定义类型
内置类型 :就是语言提供的原生数据类型,如:int/char/double/指针等。
自定义类型 :就是我们使用class/struct等关键字自己定义的类型。
#include<iostream>
using namespace std;
class Date
{
public:Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;cout << " const Date& d" << endl;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};void Func1(Date d)
{}int main()
{Date d1;Func1(d1);return 0;
}
该例子说明了Func1函数调用了拷贝函数构造。
原因是Func1(Date d),Date d 调用了拷贝。
- 若未显式定义拷贝构造,编译器会生成自动生成拷贝构造函数。自动生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(⼀个字节⼀个字节的拷贝),对自定义类型成员变量会调用他的拷贝构造。
#include<iostream>
using namespace std;
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;Date d2(d1);d2.Print();return 0;
}
- Date这样的类成员变量全是内置类型且没有指向什么资源,编译器自动生成的拷贝构造就可以完成需要的拷贝,所以不需要我们显示实现拷贝构造。像Stack这样的类,虽然也都是内置类型,但是_a指向了资源(malloc),生成了空间,浅拷贝会将地址也拷贝成一样的。堆空间释放两次,会报错。所以编译器自动生成的拷贝构造完成的值拷贝/浅拷贝不符合我们的需求,所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue这样的类型内部主要是自定义类型Stack成员,编译器自动生成的拷贝构造会调用Stack的拷贝构造,也不需要我们显示实现MyQueue的拷贝构造。
这里还有一个小技巧,如果一个类显示实现了析构并释放资源,那么他就需要显示写拷贝构造(因为释放了资源就说明当初开了资源,如果不写拷贝构造,那么系统自动生成的拷贝构造会由于浅拷贝而出错),否则就不需要。
#include<iostream>
using namespace std;
class Date
{
public:Date(int year = 1, 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;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};typedef int STDataType;
class Stack
{
public:Stack(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}// st2(st1)Stack(const Stack& st){_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);if (nullptr == _a){perror("malloc申请空间失败!!!");return;}memcpy(_a, st._a, sizeof(STDataType) * st._top);_top = st._top;_capacity = st._capacity;}void Push(STDataType x){if (_top == _capacity){int newcapacity = _capacity * 2;STDataType* tmp = (STDataType*)realloc(_a, newcapacity *sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}_a = tmp;_capacity = newcapacity;}_a[_top++] = x;}void Pop(){_a[_top - 1] = -1;--_top;}int Top(){return _a[_top - 1];}~Stack(){cout << "~Stack()" << endl;free(_a);}
private:STDataType* _a;size_t _capacity;size_t _top;
};class MyQueue
{
private:Stack _pushst;Stack _popst;
};
- 传值返回,会产生一个临时对象调用拷贝构造,传值引用返回,返回的是返回对象的别名(引用),没有产生拷贝。但是如果返回对象是一个当前函数的局部域的局部对象,函数结束就销毁了,原来的那块空间释放了,那么使用引用返回是有问题的,这时的引|用相当于一个野引用,类似一个野指针一样。会非常危险。
传引用返回可以减少拷贝,但是一定要确保返回对象,在当前函数结束后还在,才能用引用返回。不能用局部变量当返回对象。
感谢大家能看到这里,多多支持!
相关文章:
拷贝构造函数
文章目录 一、4. 拷贝构造函数 今天我们来学习拷贝构造函数。 一、4. 拷贝构造函数 如果⼀个构造函数的第⼀个参数是自身类型的引用,且任何额外的参数都有默认值,则此叫做拷贝构造函数,也就是说拷贝构造是⼀个特殊的构造函数。 它的形式是这…...
解析OVN架构及其在OpenStack中的集成
引言 随着云计算技术的发展,虚拟化网络成为云平台不可或缺的一部分。为了更好地管理和控制虚拟网络,Open Virtual Network (OVN) 应运而生。作为Open vSwitch (OVS) 的扩展,OVN 提供了对虚拟网络抽象的支持,使得大规模部署和管理…...
面试加分项:Android Framework PMS 全面概述和知识要点
在Android面试时,懂得越多越深android framework的知识,越为自己加分。 目录 第一章:PMS 基础知识 1.1 PMS 定义与工作原理 1.2 PMS 的主要任务 1.3 PMS 与相关组件的交互 第二章:PMS 的核心功能 2.1 应用安装与卸载机制 2.2 应用更新与版本管理 2.3 组件管理 第…...
征服Windows版nginx(2)
1.配置Nginx 编辑Nginx的配置文件(通常是nginx.conf),找到安装Nginx位置,如下路径: D:\nginx-1.26.2\conf 双击打开nginx.CONF编辑,在http块中添加一个新的server块,用于指定Vue项目的静态文件…...
QML states和transitions的使用
一、介绍 1、states Qml states是指在Qml中定义的一组状态(States),用于管理UI元素的状态转换和属性变化。每个状态都包含一组属性值的集合,并且可以在不同的状态间进行切换。 通过定义不同的状态,可以在不同的应用场…...
flask_sqlalchemy relationship 子表排序
背景: 使用flask_sqlalchemy 的orm 时总不可避免的遇到子表排序问题 材料: 省略 制作: 直接看下面2段代码片段(一对多关系组合),自行理解: 1、多的一方实体 from .exts import db from f…...
python+pymysql
python操作mysql 一、python操作数据库 1、下载pymysql 库, 方法一:pip3 install pymysql 或pip install pymysql 方法二:在pycharm中setting下载pymysql 2、打开虚拟机上的数据库 3、pymysql连接 dbpymysql.Connection(host&qu…...
HAL库 中断相关函数
目录 中断相关函数 函数:HAL_SuspendTick()和HAL_ResumeTick() 涉及手册: 涉及寄存器: 涉及位: 函数:HAL_UART_IRQHandler(&huart3) 存在位置: 拓展: 函数:HAL_UARTEx…...
薪资协商注意事项
根据从AI(豆包kimi)中查询的内容,以及实际面试中的经验,进行整理,供大家参考: 薪资构成:了解薪水的固定工资、绩效、补贴、奖金及其他福利等具体构成。 进行沟通时需要确认清楚是税前还是税后沟…...
【机器学习】Kaggle实战Rossmann商店销售预测(项目背景、数据介绍/加载/合并、特征工程、构建模型、模型预测)
文章目录 1、项目背景2、数据介绍3、数据加载3.1 查看数据3.2 空数据处理3.2.1 训练数据3.2.2 测试数据3.3.3 商店数据处理3.3.4 销售时间关系 4、合并数据5、特征工程6、构建训练数据和测试数据7、数据属性间相关性系数8、提取模型训练的数据集9、构建模型9.1 定义评价函数9.2…...
简化计算步骤以减少误差
简化计算步骤以减少误差 同样一个计算问题,若能减少运算次数,既可以节省计算机的计算时间,还可以减小舍人误差。 例 计算 x 255 x^{255} x255的值. 如果逐个相乘要用 254 次乘法,但若写成 x 255 x ⋅ x 2 ⋅ x 4 ⋅ x 8 ⋅…...
利用AI大模型和Mermaid生成流程图
核心点1:利用大模型生成流程图的语句(Code) 确定业务流程: 用户需要明确要绘制的业务流程,包括主要步骤、决策点以及各步骤之间的关系。将确定的业务流程以文字形式描述出来。 生成Mermaid代码: 将描述好的…...
SqlServer 杂项知识整理
目录 一. decimal字段类型二. 查询时加锁 一. decimal字段类型 ⏹decimal(8,3): 整数5位,小数3位。一共8位。 如果输入 20,会自动格式化为 20.000如果输入 20.1,会自动格式化为 20.100 -- 给数据库新增一个字段,类型要求是decimal类型 ALT…...
【Uniapp-Vue3】@import导入css样式及scss变量用法与static目录
一、import导入css样式 在项目文件中创建一个common文件夹,下面创建一个css文件夹,里面放上style.css文件,编写的是公共样式,我们现在要在App.vue中引入该样式。 在App.vue中引入该样式,这样就会使样式全局生效&#…...
Maven 中 scope=provided 和 optional=true 的区别
先说效果,maven依赖声明中加了<scope>provided</scope>,或者加了<optional>true</optional>,从效果上看是一样的,都会中断依赖传递,观察下图: 图中,项目B分别依赖了C和…...
自动化测试与智能化测试的区别和关系
自动化测试与智能化测试的区别和关系 在现代软件开发过程中,测试环节是保证软件质量的重要组成部分。随着技术的不断进步,传统的手工测试方法逐渐无法满足高效、精确的需求,自动化测试(Automated Testing)应运而生。近…...
django在线考试系统
Django在线考试系统是一种基于Django框架开发的在线考试平台,它提供了完整的在线考试解决方案。 一、系统概述 Django在线考试系统旨在为用户提供便捷、高效的在线考试环境,满足教育机构、企业、个人等不同场景下的考试需求。通过该系统,用…...
centos9设置静态ip
CentOS 9 默认使用 NetworkManager 管理网络,而nmcli是 NetworkManager 命令行接口的缩写,是一个用来进行网络配置、管理网络连接的命令工具,可以简化网络设置,尤其是在无头(没有图形界面)环境下。 1、 cd…...
使用postMessage解决iframe与父页面传参
接收传递的消息时,可以将 window.addEventListener(message, function(e) { console.log(e.data) }) 写法,更换为 window.onmessage async function(e) {} 可以避免消息发送后,多次接收该参数 父页面js IframeEvent(){const send …...
浅谈云计算05 | 云存储等级及其接口工作原理
一、云存储设备 在当今数字化飞速发展的时代,数据已然成为个人、企业乃至整个社会的核心资产。从日常生活中的珍贵照片、视频,到企业运营里的关键业务文档、客户资料,数据量呈爆炸式增长。面对海量的数据,如何安全、高效且便捷地存…...
DolphinScheduler自身容错导致的服务器持续崩溃重大问题的排查与解决
01 问题复现 在DolphinScheduler中有如下一个Shell任务: current_timestamp() { date "%Y-%m-%d %H:%M:%S" }TIMESTAMP$(current_timestamp) echo $TIMESTAMP sleep 60 在DolphinScheduler将工作流执行策略设置为并行: 定时周期调度设置…...
Linux 容器漏洞
定义:Linux 容器漏洞是指在容器技术(如 Docker、LXC 等)运行环境中存在的安全弱点。这些漏洞可能存在于容器镜像本身、容器运行时(如 runc)、容器编排工具(如 Kubernetes)或者容器与主机之间的交…...
前端依赖安装指南
前端依赖安装指南 一、NVM管理工具安装 1.在 Windows 上安装 下载 NVM for Windows 的安装程序:(最新版本可以在 nvm-windows Releases 页面 找到)运行下载的安装程序并按步骤操作。 2.配置 NVM exe安装自动配置环境变量 3. 验证 NVM 安装 验证 NVM 是否成功…...
滑动窗口限流算法:基于Redis有序集合的实现与优化
滑动窗口限流算法是一种基于时间窗口的流量控制策略,它将时间划分为固定大小的窗口,并在每个窗口内记录请求次数。通过动态滑动窗口,算法能够灵活调整限流速率,以应对流量的波动。 算法核心步骤 统计窗口内的请求数量࿱…...
JavaRestClient 客户端初始化+索引库操作
1. 介绍 ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。 Elasticsearch目前最新版本是8.0,其java客户端有很大变化。不过大多数企业使用的还是8以下版本 2. 客户端初始化 在elastic…...
理解Spark中运行程序时数据被分区的过程
在Spark中,数据分区是指将数据集分割成多个小的子集,即分区,以便在集群的多个节点上并行处理,从而提高处理效率。以下通过一个具体例子来理解: 例子背景 假设要分析一个包含100万条销售记录的数据集,每条…...
【微服务】面试 7、幂等性
幂等性概念及场景 概念:多次调用方法或接口不改变业务状态,重复调用结果与单次调用一致。例如在京东下单,多次点击提交订单只能成功一次。场景:包括用户重复点击、网络波动导致多次请求、mq 消息重复消费、代码中设置失败或超时重…...
10步打造完美ASP.NET、Web API和控制台应用程序文件夹结构
一、前言 在大型项目中,合理的文件夹结构是项目成功的关键之一。一个好的文件夹结构就像是一座井然有序的图书馆,每一本书(代码文件)都有其固定的位置,让人能迅速找到所需。它可以让团队成员更容易理解和维护代码&…...
30_Redis哨兵模式
在Redis主从复制模式中,因为系统不具备自动恢复的功能,所以当主服务器(master)宕机后,需要手动把一台从服务器(slave)切换为主服务器。在这个过程中,不仅需要人为干预,而且还会造成一段时间内服务器处于不可用状态,同时数据安全性也得不到保障,因此主从模式的可用性…...
双模充电桩发展前景:解锁新能源汽车未来的金钥匙,市场潜力无限
随着全球能源转型的浪潮席卷而来,新能源汽车行业正以前所未有的速度蓬勃发展,而作为其坚实后盾的充电基础设施,特别是双模充电桩,正逐渐成为推动这一变革的关键力量。本文将从多维度深入剖析双模充电桩的市场现状、显著优势、驱动…...
Trimble自动化激光监测支持历史遗产实现可持续发展【沪敖3D】
故事桥(Story Bridge)位于澳大利亚布里斯班,建造于1940年,全长777米,横跨布里斯班河,可载汽车、自行车和行人往返于布里斯班的北部和南部郊区。故事桥是澳大利亚最长的悬臂桥,是全世界两座手工建…...
深入解析 C++ 类型转换
简介 C 类型转换是开发者必须掌握的重要技能之一, 无论是处理隐式转换还是显式转换, 理解其背后的机制与用法至关重要. 本篇博客旨在从基础到高级全面解析 C 的类型转换, 包括实际开发中的应用场景和性能分析. 自动转换 隐式类型转换 编译器可以在无需明确指示的情况下, 将一…...
2025-1-9 QT 使用 QXlsx库 读取 .xlsx 文件 —— 导入 QXlsx库以及读取 .xlsx 的源码 实践出真知,你我共勉
文章目录 1. 导入QXlsx库2. 使用 QXlsx库 读取 .xlsx 文件小结 网上有很多教程,但太费劲了,这里有个非常简便的好方法,分享给大家。 1. 导入QXlsx库 转载链接 :https://github.com/QtExcel/QXlsx/blob/master/HowToSetProject.md…...
基于ILI9341液晶屏+STM32U5单片的显示试验
试验要求: 1、通过串口,下发两个命令 STR和PIC; 2、STR模式: (1)串口输入什么,屏幕上显示什么 (2)如果屏幕满,自动下滚 (3)输入回车&a…...
Vue.js组件开发-如何使用moment.js
在Vue.js组件开发中,需要处理日期和时间,moment.js 是一个非常有用的库。moment.js 提供了丰富的API来解析、验证、操作和显示日期和时间。 步骤: 1. 安装moment.js 首先,需要通过npm或yarn安装moment.js。在项目根目录下运行以…...
自然语言转 SQL:通过 One API 将 llama3 模型部署在 Bytebase SQL 编辑器
使用 Open AI 兼容的 API,可以在 Bytebase SQL 编辑器中使用自然语言查询数据库。 出于数据安全的考虑,私有部署大语言模型是一个较好的选择 – 本文选择功能强大的开源模型 llama3。 由于 OpenAI 默认阻止出站流量,为了简化网络配置&#…...
全面掌握APT、Vim和GCC:Ubuntu软件管理与开发指南
文章目录 Ubuntu 软件包管理器Ubuntu 软件包管理的基本概念常用的软件包管理器APTAPT常用命令 vimVim 的基本概念Vim 的工作模式Vim 的基本操作 gcc/gUbuntu 安装 gcc / g编译知识使用方法动静态函数库 Ubuntu 软件包管理器 在 **Ubuntu** 系统中,软件包管理器用于…...
项目实战--网页五子棋(用户模块)(1)
接下来我将使用Java语言,和Spring框架,实现一个简单的网页五子棋。 主要功能包括用户登录注册,人机对战,在线匹配对局,房间邀请对局,积分排行版等。 这篇文件讲解用户模块的后端代码 1. 用户表与实体类 …...
【Ubuntu与Linux操作系统:七、系统高级管理】
第7章 系统高级管理 7.1 Linux进程管理 进程是Linux系统中的基本运行单位,代表一个正在执行的程序。Linux通过进程管理实现多任务并发处理,支持用户高效利用系统资源。 1. 进程的基本概念: 进程状态:进程在运行过程中可能处于运…...
多线程面试相关
线程基础知识 线程与进程的区别 并行和并发的区别 创建线程的方式 Runnable和Callable有什么区别 run()方法和start()方法的区别 小结 线程包含哪些状态,各个状态之间如何变化 线程按顺序执行 notify()和notifyAll()的区别 Java中的wait方法和sleep方法的不同 如何…...
WMS仓库管理系统,Vue前端开发,Java后端技术源码(源码学习)
一、项目背景和建设目标 随着企业业务的不断扩展,仓库管理成为影响生产效率、成本控制及客户满意度的重要环节。为了提升仓库作业的透明度、准确性和效率,本方案旨在构建一套全面、高效、易用的仓库管理系统(WMS)。该系统将涵盖库…...
【前端】【CSS3】基础入门知识
目录 如何学习CSS 1.1什么是CSS编辑 1.2发展史 1.三种导入方式 1.1、行内样式 1.2、外部样式 1.3、嵌入方式 2.选择器 2.1、基本选择器 (1)元素选择器 (2)类选择器 (3)id选择器:必…...
51单片机——定时器中断(重点)
STC89C5X含有3个定时器:定时器0、定时器1、定时器2 注意:51系列单片机一定有基本的2个定时器(定时器0和定时器1),但不全有3个中断,需要查看芯片手册,通常我们使用的是基本的2个定时器ÿ…...
Android原生开发同一局域网内利用socket通信进行数据传输
1、数据接收端代码如下,注意:socket 接收信息需要异步运行: // port 端口号自定义一个值,比如 8888,但需和发送端使用的端口号保持一致 ServerSocket serverSocket new ServerSocket(port); while (true) {//这里为了…...
基于微信小程序的食堂线上预约点餐系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
算法初学者(图的存储)链式前向星
知识储备:概念,存储,遍历,最短路,最小生成树,拓扑排序-关键路径 图的存储:邻接矩阵,邻接表,十字链表,多重邻接表,边集数组 其中:邻接…...
Github 2025-01-11 Rust开源项目日报 Top10
根据Github Trendings的统计,今日(2025-01-11统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10C项目1Swift项目1Yazi - 快速终端文件管理器 创建周期:210 天开发语言:Rust协议类型:MIT LicenseStar数量:5668 个Fork数量:122…...
Leetcode 3419. Minimize the Maximum Edge Weight of Graph
Leetcode 3419. Minimize the Maximum Edge Weight of Graph 1. 解题思路2. 代码实现3. 算法优化 题目链接:3419. Minimize the Maximum Edge Weight of Graph 1. 解题思路 这一题我的思路就是二分法,找到能够完成遍历的临界值即可。 但是自己实际在…...
深入理解数据库索引及其优化策略
数据库作为现代应用系统的核心组件之一,如何高效地存储和检索数据成为开发者关注的焦点。 在处理大规模数据时,数据库索引 是提升查询性能的关键技术之一。本文将深入探讨数据库索引的工作原理、常见类型、创建索引的策略以及如何优化索引,以…...
安科瑞 Acrel-1000DP 分布式光伏监控系统在工业厂房分布式光伏发电项目中的应用
吕梦怡 18706162527 摘 要:常规能源以煤、石油、天然气为主,不仅资源有限,而且会造成严重的大气污染,开发清洁的可再生能源已经成为当今发展的重要任务,“节能优先,效率为本”的分布式发电能源符合社会发…...