【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;
}

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

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

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

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

相关文章

什么是MapReduce

1.1 MapReduce到底是什么 Hadoop MapReduce是一个软件框架&#xff0c;基于该框架能够容易地编写应用程序&#xff0c;这些应用程序能够运行在由上千个商用机器组成的大集群上&#xff0c;并以一种可靠的&#xff0c;具有容错能力的方式并行地处理上TB级别的海量数据集。这个定…

记一次生产jvm oom问题

前言 jvm添加以下参数&#xff0c;发生OOM时自动导出内存溢出文件 -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/opt 内存分析工具&#xff1a; MAT, 下载地址&#xff1a;Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation&#xff0c; 注意工具地址…

企业如何定制化“可靠的”系统,实现数字化转型?

二十大提出高质量发展是首要任务&#xff0c;为顺应数字经济时代的发展&#xff0c;数字化转型正不断赋能各行各业。越来越多的企业管理者也意识到数字化转型是帮助企业提升内部运营效率&#xff0c;提升业务开展效率&#xff0c;减低企业成本的有效手段。 那么如何推动企业数字…

论文阅读——SimpleClick

SimpleClick: Interactive Image Segmentation with Simple Vision Transformers 模型直接在VIT上增加交互是分割 用VIT MAE方法训练的预训练权重 用交互式分割方法微调&#xff0c;微调流程&#xff1a; 1、在当前分割自动模拟点击&#xff0c;没有人为提供的点击 受到RITM启发…

马斯克称创建OPENAI是希望开源非营利 但现在却闭源和被微软控制

作为 OPENAI 的联合创始人&#xff0c;埃隆马斯克其实是个坚定的 “反” 人工智能的人&#xff0c;原因是马斯克认为人工智能是人类文明最大的风险之一&#xff0c;应该进行严格监管&#xff0c;至少应该由国家级层面的监管。 2015 年马斯克联合 Sam Altman (OPENAI 现任 CEO)…

智慧城市与数字孪生:共创未来城市新篇章

一、引言 随着科技的飞速发展&#xff0c;智慧城市与数字孪生已成为现代城市建设的核心议题。智慧城市注重利用先进的信息通信技术&#xff0c;提升城市治理水平&#xff0c;改善市民生活品质。而数字孪生则通过建立物理城市与数字模型之间的连接&#xff0c;为城市管理、规划…

springmvc+ssm+springboot房屋中介服务平台的设计与实现 i174z

本论文拟采用计算机技术设计并开发的房屋中介服务平台&#xff0c;主要是为用户提供服务。使得用户可以在系统上查看房屋出租、房屋出售、房屋求购、房屋求租&#xff0c;管理员对信息进行统一管理&#xff0c;与此同时可以筛选出符合的信息&#xff0c;给笔者提供更符合实际的…

IOBR2 更新(学习自备)

IOBR查看其收录的相关基因集(自备)_肿瘤 tme特征 iobr-CSDN博客 IOBR2&#xff1a;多维度解析肿瘤微环境 - 知乎 (zhihu.com) 学习手册&#xff1a;https://iobr.github.io/book/ &#xff08;里面有详细教程&#xff09; 系统综合的分析工具&#xff08;Immuno-Oncology Bi…

【Web】CTFSHOW 常用姿势刷题记录(全)

目录 web801 web802 web803 web804 web805 web806 web807 法一&#xff1a;反弹shell 法二&#xff1a;vps外带 web808 web809 web810 web811 web812 web813 web814 web815 web816 web817 web818 web819 web820 web821 web822 web823 web824 web825…

NXP实战笔记(七):S32K3xx基于RTD-SDK在S32DS上配置ICU输入捕获

目录 1、概述 2、输入捕获SDK配置 2.1、SAIC中断方式 2.2、IPWM或者IPM 1、概述 输入捕获&#xff0c;可以抓取高电平时间、低电平时间、占空比、周期、边沿检测与回调函数、边沿计数&#xff08;ABZ解码&#xff09;、时间戳、唤醒中断。 记录一下根据Emios模块实现上述部分…

CSS列表学习2

之前学习了列表&#xff1b;继续熟悉&#xff1b; <!DOCTYPE html> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/><title></title><meta charset"utf-8" /><…

常用显示屏学习——LCD12864(含高级驱动程序)

LCD12864液晶显示屏 屏幕介绍 ① 可显示四行字符&#xff0c;每行可显示8个汉字或者16个数字和字母&#xff1b; ②可串行通信和并行通信&#xff1b; ③ 串口接口管脚信号 通信方法 &#xff08;一&#xff09;八位并行通信方法 &#xff08;二&#xff09;串行通信方法 用…

iMazing3终极iPhone数据设备管理软件

iMazing是一款功能丰富的iOS设备管理软件&#xff0c;具备多种实用功能&#xff0c;以下是它的主要功能的详细介绍&#xff1a; iMazing3Mac-最新绿色安装包下载如下&#xff1a; https://wm.makeding.com/iclk/?zoneid49816 iMazing3Win-最新绿色安装包下载如下&#xff1…

08 Redis之集群的搭建和复制原理+哨兵机制+CAP定理+Raft算法

5 Redis 集群 2.8版本之前, Redis采用主从集群模式. 实现了数据备份和读写分离 2.8版本之后, Redis采用Sentinel哨兵集群模式 , 实现了集群的高可用 5.1 主从集群搭建 首先, 基本所有系统 , “读” 的压力都大于 “写” 的压力 Redis 的主从集群是一个“一主多从”的读写分…

论文阅读:Ground-Fusion: A Low-cost Ground SLAM System Robust to Corner Cases

前言 最近看到一篇ICRA2024上的新文章&#xff0c;是关于多传感器融合SLAM的&#xff0c;好像使用了最近几年文章中较火的轮式里程计。感觉这篇文章成果不错&#xff0c;代码和数据集都是开源的&#xff0c;今天仔细读并且翻译一下&#xff0c;理解创新点、感悟研究方向、指导…

lxml库和Xpath提取网页数据的基础与实战:完整指南与实战【第92篇—提取网页】

使用lxml库和Xpath提取网页数据的基础与实战 在网络爬虫和数据抓取中&#xff0c;从网页中提取所需信息是一项常见的任务。lxml库和Xpath是Python中用于解析和提取HTML/XML数据的强大工具。本文将介绍lxml库的基础知识&#xff0c;以及如何使用Xpath表达式来准确地提取网页数据…

Flutter Slider自定义滑块样式 Slider的label标签框常显示

1、自定义Slider滑块样式 Flutter Slider控件的滑块系统样式是一个圆点&#xff0c;thumbShape默认样式是RoundSliderThumbShape&#xff0c;如果想要使用其它的样式就需要自定义一下thumbShape&#xff1b; 例如需要一个上图样式的&#xff08;圆点半透明圆形边框&#xff09…

游戏同步+游戏中的网络模块

原文链接&#xff1a;游戏开发入门&#xff08;九&#xff09;游戏同步技术_游戏数据同步机制流程怎么开发-CSDN博客 游戏开发入门&#xff08;十&#xff09;游戏中的网络模块_游戏开发组网-CSDN博客 3.同步技术的基本常识&#xff1a; a.同步给谁&#xff1f;某个用户&…

基于ZYNQ的PCIE高速数据采集卡的设计(二)总体设计与上位机

采集卡总体设计及相关技术 2.1 引言 本课题是来源于雷达辐射源识别项目&#xff0c;需要对雷达辐射源中频信号进行采集传输 和存储。本章基于项目需求&#xff0c;介绍采集卡的总体设计方案。采集卡设计包括硬件设计 和软件设计。首先对采集卡的性能和指标进行分析&#x…

Nginx使用

Nginx 常用命令&#xff1a; nginx -s stop 快速关闭Nginx&#xff0c;可能不保存相关信息&#xff0c;并迅速终止web服务。 nginx -s quit 平稳关闭Nginx&#xff0c;保存相关信息&#xff0c;有安排的结束web服务。 nginx -s reload 因改变了Nginx相关配置…