C++之类和对象三

目录

拷贝构造函数

定义铺垫

浅拷贝

深拷贝

总结


拷贝构造函数

那在创建对象时,可否创建一个与一个对象一某一样的新对象呢?

定义铺垫

构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象 创建新对象时由编译器自动调用。

拷贝构造函数也是特殊的成员函数,其特征如下:

  1.  拷贝构造函数是构造函数的一个重载形式
  2.  拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
  3.  若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷 贝,这种拷贝我们叫做浅拷贝,或者值拷贝。
  4.  那么编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,我们还需要自己实现吗?当然像 日期类这样的类是没必要的
class Date
{
public:
	Date()
	{
		_year = -1;
		_month = -1;
		_day = -1;
	}
	Date(int year, int month, int day)
	{
		_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;
		cout << &_year << "-" << &_month << "-" << &_day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2024, 4, 18);
	d1.Print();
	Date d2(d1);
	d2.Print();
	return 0;
}

在这里我们给一段代码。

其中要注意这里的拷贝构造是引用传参

我们发现他们的打印结果相同 地址也相同

这就是拷贝函数

浅拷贝

class Date
{
public:
	Date()
	{
		_year = -1;
		_month = -1;
		_day = -1;
	}
	Date(int year, int month, int day)
	{
		_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;
		cout << &_year << "-" << &_month << "-" << &_day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
void func(Date d)
{
	d.Print();
}
int main()
{
	Date d1(2024, 4, 18);
	func(d1);
	return 0;
}

然后我们在进行调试 

我们会发现当我们的d1初始化完后,我们下一步按F11时,会先进入Date的拷贝构造中,然后再调用func函数

所以

调用func得先传参,自动以类型对象传值传参要调用拷贝构造

当然了我们也可以不去使用拷贝构造

比如使用指针或者使用引用

void func(Date& d)
{
	d.Print();
}
void func(Date* d)
{
	d.Print();
}

一个是d1的地址一个是d1的别名

在这里我们还可以继续更改一下代码

Date(const Date& d)
	{
		this->_year = d._year;
		this->_month = d._month;
		this->_day = d._day;
	}

加上一个const去缩小权限

因为我们只是拷贝构造不需要改变值

这里也是存在this指针的

Date(const Date& d)
	{
		this->_year = d._year;
		this->_month = d._month;
		this->_day = d._day;
	}

拷贝构造的形式有很多

int main()
{
	Date d1(2024, 4, 18);
	Date d2 = d1;
    Date d3(d2);
	return 0;
}

这种类似于赋值的形式也是拷贝构造

class Date
{
public:
	Date()
	{
		_year = -1;
		_month = -1;
		_day = -1;
	}
	Date(int year, int month, int day)
	{
		_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;
		cout << &_year << "-" << &_month << "-" << &_day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
void func(Date d)
{
	d.Print();
}
int main()
{
	Date d1(2024, 4, 18);
	Date d2 = d1;
	Date d3(d2);
	d2.Print();
	d3.Print();
	return 0;
}

我们把我们的拷贝构造给注释掉

然后在进行打印会发现依旧会进行拷贝构造

原因是拷贝构造是默认的成员函数,不写他会进行值的拷贝,简称值拷贝

深拷贝

但如果是栈呢?

struct stack
{
public:
	int* a;
	int size;
	int capacity;
	void Init(int n = 4)
	{
		a = (int*)malloc(sizeof(int) * n);
		if (a == nullptr)
		{
			perror("malloc fail");
			return;
		}
		//...
		size = 0;
		capacity = n;
	}
	void Push(int x)
	{
		a[size++] = x;
	}
};
int main()
{
	/*Date d1(2024, 4, 18);
	Date d2 = d1;
	Date d3(d2);
	d2.Print();
	d3.Print();*/
	stack st;
	st.Push(1);
	st.Push(1);
	st.Push(1);
	stack st1 = st;
	return 0;
}

 我们会发现代码崩溃了

但拷贝是否完成了呢?

拷贝完成了

我们这里也是完成了值拷贝

这里会存在一个大问题

如果只进行了值拷贝,也就是说这两个栈都是使用的同一块内存,如果进行析构的话会进行两次,出现错误,所以只要是存在浅拷贝/值拷贝,就会可能出现一定的错误

所以,浅拷贝的类我们可以进行值拷贝,但如果是深拷贝就需要慎重考虑了

 所以这里怎么办呢?

我们可以在构造函数时进行一定的改进

struct stack
{
public:
	/*void Init(int n = 4)
	{
		a = (int*)malloc(sizeof(int) * n);
		if (a == nullptr)
		{
			perror("malloc fail");
			return;
		}
		size = 0;
		capacity = n;
	}*/
	void Push(int x)
	{
		a[size++] = x;
	}
	stack(const stack& st)
	{
		a = (int*)malloc(sizeof(int) * st.capacity);
		if (a == nullptr)
		{
			perror("malloc fail");
			return;
		}
		memcpy(a, st.a, sizeof(int) * st.size);
		size = st.size;
		capacity = st.capacity;
	}
	stack()
	{
		a = (int*)malloc(sizeof(int) * capacity);
		if (a == nullptr)
		{
			perror("malloc fail");
			return;
		};
		size = capacity = 4;
	}
	~stack()
	{
		a = nullptr;
		size = capacity = 0;
	}
private:
	int* a = nullptr;
	int size = 4;
	int capacity = 4;
};
int main()
{
	/*Date d1(2024, 4, 18);
	Date d2 = d1;
	Date d3(d2);
	d2.Print();
	d3.Print();*/
	stack st1;
	st1.Push(1);
	st1.Push(1);
	st1.Push(1);

	stack st2 = st1;
	return 0;
}

这样我们的代码就可以正常运行拷贝构造了

总结

总结一下:

  1. 如果没有管理资源,一般情况下不需要写拷贝构造,默认生成的拷贝构造就可以,如:Date

  2. 如果自定义类型的话,内置类型没有指向资源,也类似默认生成的拷贝构造就可以
  3. 一般情况下,不需要显示写析构函数,就不需要写拷贝构造
  4. 如果内部有指针或者有一些只想资源,需要显示写析构函数,通常就需现实些构造完成深拷贝。如:stack,queue

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年华中杯B题论文发布+数据预处理问题一代码免费分享

【腾讯文档】2024年华中杯B题资料汇总 https://docs.qq.com/doc/DSExMdnNsamxCVUJt 行车轨迹估计交通信号灯周期问题 摘要 在城市化迅速发展的今天&#xff0c;交通管理和优化已成为关键的城市运营问题之一。本文将基于题目给出的数据&#xff0c;对行车轨迹估计交通信号灯…

【1577】java网吧收费管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 网吧收费管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…

一篇文章搞定Jenkins自动化部署JDK17+SpringBoot3.X+新版AlibabaCloud打包Docker镜像推送私有镜像仓库

&#x1f680; 作者 &#xff1a;“二当家-小D” &#x1f680; 博主简介&#xff1a;⭐前荔枝FM架构师、阿里资深工程师||曾任职于阿里巴巴担任多个项目负责人&#xff0c;8年开发架构经验&#xff0c;精通java,擅长分布式高并发架构,自动化压力测试&#xff0c;微服务容器化k…

Redis中的订阅发布(二)

订阅与发布 订阅频道 每当客户端执行SUBSCRIBE命令订阅某个或某些频道的时候&#xff0c;服务器都会将客户端与被订阅的频道 在pubsub_channels字典中进行关联。 根据频道是否已经有其他订阅者&#xff0c;关联操作分为两种情况执行: 1.如果频道已经有其他订阅者&#xff0c…

微信小程序echart图片不显示 问题解决

目录 1.问题描述&#xff1a;2.解决方法&#xff1a;2.1第一步2.2第二步2.2效果 小结&#xff1a; 1.问题描述&#xff1a; echart图片不显示 图片&#xff1a; 2.解决方法&#xff1a; 2.1第一步 给wxml中的ec-canvas组件添加宽高样式&#xff1a;style"width: 100%…

图文教程 | Git安装配置、常用命令大全以及常见问题

前言 因为多了一台电脑&#xff0c;平时写一些代码&#xff0c;改一些文件&#xff0c;用U盘存着转来转去特别麻烦。于是打算用Git管理我的文件&#xff0c;方便在两个终端之间传输数据啥的。也正好给新电脑装好Git。 &#x1f4e2;博客主页&#xff1a;程序源⠀-CSDN博客 &…

MathType安装导致的Word粘贴操作出现运行时错误‘53’:文件未找到:MathPage.WLL

MathType安装导致的Word粘贴操作出现运行时错误‘53’&#xff1a;文件未找到&#xff1a;MathPage.WLL 解决方案 1、确定自己电脑的位数&#xff1b; 2、右击MathType桌面图标&#xff0c;点击“打开文件所在位置”&#xff0c;然后找到MathPage.WLL &#xff0c;复制一份进行…

深度 | 践行绿色健康可持续发展,这家企业提供了价值范本

文 | 螳螂观察 作者 | 余一 近段时间以来&#xff0c;小米SU7热度一直不减&#xff0c;在展露小米强大品牌号召力的同时&#xff0c;也侧面体现出了当前消费者对于新能源汽车的喜爱。 而消费者选择新能源汽车时&#xff0c;环保因素也起到了至关重要的作用。像前几日&#x…

PolarDB闪电助攻,《香肠派对》百亿好友关系实现毫秒级查询

云原生数据库PolarDB分布式版&#xff08;PolarDB for Xscale&#xff0c;简称PolarDB-X&#xff09;有极强的线性扩展能力&#xff0c;能够多写多读&#xff1b;它的全局索引能力&#xff0c;是分布式改造的利器&#xff0c;成功解决了传统分布式方案中多维度查询的难题&#…

探究欧拉恒等式的美学与数学威力

正如老子所述&#xff0c;“道生一&#xff0c;一生二&#xff0c;二生三&#xff0c;三生万物”&#xff0c;数学作为人类认知自然法则的语言&#xff0c;其数系的不断发展象征着对世界理解的深化。从自然数经由分数、无理数至复数&#xff0c;复数虽看似反直觉&#xff0c;却…

探索AI大模型:理论、技术与应用

引言 近年来&#xff0c;随着深度学习技术的迅猛发展&#xff0c;AI大模型已经成为人工智能领域的重要研究方向和热点话题。AI大模型&#xff0c;指的是拥有巨大参数规模和强大学习能力的神经网络模型&#xff0c;如BERT、GPT等&#xff0c;这些模型在自然语言处理、计算机视觉…

es安装中文分词器

下载地址&#xff0c;尽量选择和自己本地es差不多的版本 https://github.com/infinilabs/analysis-ik/releases 下载好&#xff0c;解压&#xff0c;把里面的文件放到es的plugins/ik目录下 把plugin-descriptor.properties文件里的es版本改成自己对应的 再启动es&#xff0c;能…

2W 3KVDC 隔离单、双输出 DC/DC 电源模块——TPH 系列

TPH系列是一款2W&#xff0c;单、双输出隔离电源模块&#xff0c;特别适合板上只有一种电压而要求有正负电源的场合&#xff0c;工业级温度范围–40℃到105℃&#xff0c;在此温度范围内都可以稳定输出2W&#xff0c;并且效率非常高&#xff0c;高达86%&#xff0c;温升非常低&…

OKCC搭建配置什么样的服务器合适

OKCC呼叫中心系统是一种采用软硬件结合的架构方式、及分布式的IP技术&#xff0c;从多角度为企业提供整合的一体化解决方案。因此&#xff0c;搭建OKCC呼叫中心系统所使用的服务器应该满足以下几点要求&#xff1a; 稳定性&#xff1a;服务器需要具有较高的稳定性和可靠性&…

MinIO + Prometheus + Grafana docker部署

文章目录 说明MinIO简介MinIO 容器化部署Prometheus服务地址配置方法一&#xff1a;先部署后修改方法二&#xff1a;部署时修改compose文件&#xff08;未验证&#xff09; MinIO Access Key配置Prometheus 容器化部署MinIO 生成抓取配置修改Prometheus配置文件Grafana 容器化部…

iframe和 blob实现JS,CSS,HTML直接当前页预览

先贴效果图&#xff1a; <template><div><div class"aaa"></div><div class"btn-run" click"tres">运行</div></div></template><script>import { mapState } from vuex;export default …

在线编辑器 CodeMirror

如何优雅的在网页显示代码 如果开发在线编辑器 引入资源&#xff1a; <link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.60.0/codemirror.min.css"><script src"https://cdnjs.cloudflare.com/ajax/libs/c…

【网安小白成长之路】8.sql注入操作1

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f51e; 《网安小白成长之路(我要变成大佬&#x1f60e;&#xff01;&#xff01;)》真实小白学习历程&#xff0c;手把手带你一起从入门到入狱&#x1f6ad; &…

店前台安装水离子雾化壁炉前和装后对比

当酒店前台装上水离子雾化壁炉后&#xff0c;整体氛围和客户体验都会发生显著的变化&#xff1a; 装前&#xff1a; 普通的前台氛围&#xff1a;前台可能显得比较普通和传统&#xff0c;可能缺乏独特的装饰元素或视觉焦点。 视觉上缺乏吸引力&#xff1a;前台空间可能比较朴…

现代商业中首席人工智能官(CAIO)的角色与影响

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…