详解拷贝构造

拷贝构造的功能

写法:

拷贝构造函数的参数为什么是引用类型

系统自动生成的拷贝构造函数

拷贝构造的深拷贝与浅拷贝

概念

浅拷贝:

深拷贝

小结


拷贝构造的功能

拷贝构造函数可以把曾经实例化好的对象的数据拷贝给新创建的数据 ,可见说拷贝构造函数在功能上是构造函数的另一种形式。都是让对象初始化。

写法:

拷贝构造函数在语法层是构造函数的重载,函数名就是类名,无返回值,参数是该类类型对象的引用(为了保护被引用对象数据不被破坏,会在类型前面加上const)

 Date(const Date& d) //以日期类为例,定义拷贝构造的写法
Date d1;Date d2(d1); //以日期类为例,实例化对象时的写法

拷贝构造函数的参数为什么是引用类型

下面是定义的日期类的拷贝构造函数,但参数并不是引用类型

Date(const Date d)
{_year = d._year;_month = d._month;_day = d._day;
}

因为是传值,实例化对象时需要调用拷贝构造函数把数据拷贝过来,但拷贝数据函数的参数又需要掉用拷贝构造函数,如此就死循环了,拷贝构造函数会被无限调用。如图所示这种情况编译器会强制报错

系统自动生成的拷贝构造函数

若未显式定义,编译器会生成默认的拷贝构造函数 默认的拷贝构造函数对象按内存存储 按字节序 完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝
下面代码中定义了一个时间类 Time ,又定义了一个日期类 Date , 时间类在日期类里实例化了对象_t,_t就是日期类的自定义类型,但并没有定义日期类的拷贝构造函数。那么系统自动生成的拷贝构造函数会怎么处理自定义类型_t和内置类型的年月日呢?
class Time {   //时间类
public:Time() {
_hour = 1;
_minute = 1;
_second = 1;
}Time(const Time& t) //自定义时间类的拷贝构造函数
{
_hour = t._hour;
_minute = t._minute;
_second = t._second;
}private:int _hour;
int _minute;
int _second;
};class Date  //日期类,但没有自定义拷贝构造函数
{private:
// 基本类型(内置类型)int _year;int _month;int _day;// 自定义类型
Time _t;  //时间类实例化对象 _t};int main(){Date d1;
Date d2(d1); //拷贝对象d1的数据// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数return 0;
}

只需明晰一点即可,系统自动生成的默认拷贝构造对内置类型进行浅拷贝对自定义类型,会调用自定义类型的拷贝构造函数,若自定义类型并未定义拷贝构造函数,系统便会自动生成。

下图是代码执行示意图

下图是逻辑示意图

拷贝构造的深拷贝与浅拷贝

概念

浅拷贝:

又称值拷贝,是按字节序拷贝的,通俗的讲别的数据长啥样就拷贝啥样。

浅拷贝的细节:下面代码中还是定义了一个日期类,但增加了一个int*的变量它指向一块空间。这是让默认构造函数进行浅拷贝会发生什么呢?

class Date //日期类,并没有定义拷贝构造函数
{
public:Date()//构造函数{_year = 1;_month = 1;_day = 1;_a = (int*)malloc(sizeof(int) * 7); //开辟空间并把空间的值初始化for (int i = 0; i < 7; i++){_a[i] = 0;}}private:int _year;int _month;int _day;int* _a; //指向一块空间
};
int main()
{Date d; Date d1(d); //拷贝d的值
}

结果:d对象和d1对象的数据会一模一样,如下图

我们发现d对象的值和d1对象的值一模一样,并且d对象中的_a和d1对象中的_a都指向同一块空间。如下图

上述就值浅拷贝的坏处,d1对象的_a并没有申请资源而是直接指向了d对象_a的空间,如果想让d1

_a也申请空间就需要深拷贝,想要深拷贝就需要自己定义一个拷贝构造函数,该拷贝构造函数如何申请空间要根据不同的场景具体实现。

深拷贝

下面的代码是对上面代码的改造,

class Date
{
public:Date() //构造函数{_year = 1;_month = 1;_day = 1;_a = (int*)malloc(sizeof(int) * 7);for (int i = 0; i < 7; i++){_a[i] = 0;}}Date(const Date& d) //拷贝构造函数{_year = d._year; _month = d._month;_day = d._day;_a = (int*)malloc(sizeof(int) * (sizeof(d._a) / sizeof(d._a[0])));  //开辟空间for (int i = 0; i < (sizeof(d._a) / sizeof(d._a[0])); i++)  //赋值{_a[i] = d._a[i];}}private:int _year;int _month;int _day;int* _a;
};
int main()
{Date d;Date d1(d);
}

d1对象的_a会独自开空间并且拷贝d对象的数据,如下图这样就完成了拷贝构造的深拷贝了。

小结

拷贝构造是构造函数的重载。参数是该类类型的引用(一般会加上const),不加引用在逻辑是会让拷贝函数无限调用,此时编译器会报错。如果未显示定义拷贝构造函数,编译器会生成默认的拷贝构造函数默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。浅拷贝又称值拷贝,是按字节序拷贝的,通俗的讲别的数据长啥样就拷贝啥样。而深拷贝会申请资源(空间)再赋值。

另外我还为大家准备了几篇不错的博客

构造函数:  http://t.csdnimg.cn/MdHiA

希尔排序:   http://t.csdnimg.cn/uxSBG

堆排序的时间复杂度:  http://t.csdnimg.cn/OJLzI

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

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

相关文章

架构师系列-搜索引擎ElasticSearch(八)- 集群管理故障恢复

故障转移 集群的master节点会监控集群中的节点状态&#xff0c;如果发现有节点宕机&#xff0c;会立即将宕机节点的分片数据迁移到其它节点&#xff0c;确保数据安全&#xff0c;这个叫做故障转移。 下图中node1是主节点&#xff0c;其他两个节点是从节点 节点故障 此时node1…

数模 线性规划模型理论与实践

线性规划模型理论与实践 1.1 线性规划问题 在人们的生产实践中&#xff0c;经常会遇到如何利用现有资源来安排生产&#xff0c;以取得最大经济效益的问题。此类问题构成了运筹学的一个重要分支一数学规划&#xff0c;而线性规划(Linear Programming 简记LP)则是数学规划的一个…

深入剖析MongoDB集群架构设计

目录 一、MongoDB集群架构介绍 1.1 主从复制 1.2 副本集 1.3 分片集群 二、副本集 3.1 主节点选举 3.2 oplog 3.2 主从同步 三、分片集群 3.1 分片策略 3.2 分片键的选择 3.3 何时选择分片集群 四、总结 一、MongoDB集群架构介绍 MongoDB 有三种集群架构模式&#xff0c;分…

bugku-web-文件上传

提示他的名字是margin&#xff0c;给他一个图片文件&#xff0c;不要php文件 上传一句话木马的图片 抓包&#xff0c;后缀改为php 提示无效文件&#xff0c;即后台还会检测一次后缀 测试后台系统 为linux系统 开始绕过 截断绕过 上传成功&#xff0c;但是会变为jpg 开始分析…

【opencv】示例-stiching.cpp 图像拼接

#include "opencv2/imgcodecs.hpp" // 导入opencv图像编码功能库 #include "opencv2/highgui.hpp" // 导入opencv高层用户界面功能库 #include "opencv2/stitching.hpp" // 导入opencv图像拼接功能库#include <iostream> // 导入输入输出…

解决 php 连接mysql数据库时报错:Fatal error: Class ‘mysqli’ not found in问题

如果你没找到php.ini但只有php.ini-development或者php.ini-production。 首先先创建一个php.ini然后复制php.ini-development或者php.ini-production到里面去。 然后在php.ini里面进行操作。一共两步。 第一步&#xff0c;将extension前面的分号去掉 第二步&#xff0c;更换为…

AutoGen - Build Powerful AI Agents with ChatGPT/GPT-4

原文:AutoGen - Build Powerful AI Agents with ChatGPT/GPT-4 | MLExpert - Crush Your Machine Learning interview In this tutorial, well explore AutoGen1, a Microsoft library that lets you create LLM applications with agents. These agents can communicate and …

基于Docker构建CI/CD工具链(六)使用Apifox进行自动化测试

添加测试接口 在Spring Boot Demo项目里实现一个简单的用户管理系统的后端功能。具体需求如下&#xff1a; 实现了一个RESTful API&#xff0c;提供了以下两个接口 &#xff1a; POST请求 /users&#xff1a;用于创建新的用户。GET请求 /users&#xff1a;用于获取所有用户的列…

ChatGPT在线网页版

ChatGPT镜像 今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像…

YOLTV8 — 大尺度图像目标检测框架(欢迎star)

YOLTV8 — 大尺度图像目标检测框架【ABCnutter/YOLTV8: &#x1f680;】 针对大尺度图像&#xff08;如遥感影像、大尺度工业检测图像等&#xff09;&#xff0c;由于设备的限制&#xff0c;无法利用图像直接进行模型训练。将图像裁剪至小尺度进行训练&#xff0c;再将训练结果…

Matlab隐式方程拟合【案例源码+视频教程】|隐函数拟合|非线性拟合|视频教程

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《复杂函数拟合案例分享》本专栏旨在提供 1.以案例的形式讲解各类复杂函数拟合的程序实现方法&#xff0c;并提供所有案例完整源码&#xff1b;2.…

OpenHarmony实战开发-Actor并发模型对比内存共享并发模型

内存共享并发模型指多线程同时执行复数任务&#xff0c;这些线程依赖同一内存并且都有权限访问&#xff0c;线程访问内存前需要抢占并锁定内存的使用权&#xff0c;没有抢占到内存的线程需要等待其他线程释放使用权再执行。 Actor并发模型每一个线程都是一个独立Actor&#xf…