C++之类和对象三

news2024/12/25 23:57:07

目录

拷贝构造函数

定义铺垫

浅拷贝

深拷贝

总结


拷贝构造函数

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

定义铺垫

构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用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.coloradmin.cn/o/1607725.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考-系统集成项目管理中级--项目质量管理(输入输出很重要!!!本章占分较高,着重复习)

本章历年考题分值统计 本章重点常考知识点汇总清单 5、成本效益分析法:对每个质量活动进行成本效益分析&#xff0c;就是要比较其可能的成本与预期的效益。达到质量要求的主要效益包括减少返工、提高生产率、降低成本、提升干系人满意度及提升赢利能力。(掌握)17下64考题 本章…

IDEA配置Maven环境

黑马程序员JavaWeb开发教程 文章目录 如果当前有已经打开项目的话&#xff0c;File -> Close Project 到以下页面之后选择 Customize -> All settings… 配置maven的安装目录&#xff0c;maven的配置文件&#xff0c;maven的本地仓库&#xff08;修改完成之后一定要先…

DRF 序列化类保存save源码

【七】序列化保存save源码 【1】介绍 无论是创建还是修改数据&#xff0c;都需要执行save方法&#xff0c;再前面的使用中都没有再里面添加过参数 其实save中可以给额外参数比如.save(timedatetime.datetime.now())这个需要模型表中有time的字段&#xff0c;结果就是将当前时…

【YOLOv5】利用Kaggle的GPU训练(运行)yolov5模型(项目)

文章目录 &#xff08;一&#xff09;下载YOLOv5源码&#xff08;二&#xff09;修改YOLOv5源码1、修改输出文件的保存路径&#xff08;适应Kaggle的输出路径&#xff09;2、在data文件夹中新建一个yaml文件3、在 train.py 中修改data路径4、指定训练的轮数5、修改模型配置文件…

C语言 | Leetcode C语言题解之第38题外观数列

题目&#xff1a; 题解&#xff1a; class Solution { public:string countAndSay(int n) {string s "1", ans "1";for (int i 2; i < n; i) {ans "";for (int j 0; j < int(s.size()); ) {int k j;while(k < int(s.size()) &am…

使用yolov8 进行实例分割训练

1、基于windows 的ISAM标注 直接下载安装包&#xff0c;解压后即可使用 链接&#xff1a;https://pan.baidu.com/s/1u_6jk-7sj4CUK1DC0fDEXQ 提取码&#xff1a;c780 2、标注结果转yolo格式 通过ISAM标注后的json文件路径 原始json格式如下&#xff1a; ISAM.json 转 yolo.…

[阅读笔记1][GPT-3]Language Models are Few-Shot Learners

首先讲一下GPT3这篇论文&#xff0c;文章标题是语言模型是小样本学习者&#xff0c;openai于2020年发表的。 这篇是在GPT2的基础上写的&#xff0c;由于GPT2还存在一些局限&#xff0c;这篇对之前的GPT2进行了一些完善。GPT2提出了多任务学习&#xff0c;也就是可以零样本地用在…

深入剖析跨境电商平台风控机制,探索测评安全与稳定的秘诀

在跨境电商测评市场鱼龙混杂的当下&#xff0c;测评过程中可能隐藏的陷阱保持高度警觉。多年的测评经验告诉我们&#xff0c;选择一个适合的测评系统对于项目的成功至关重要。近年来&#xff0c;测评技术如雨后春笋般涌现&#xff0c;市场上涌现出众多测评系统&#xff0c;覆盖…

SQL-Oracle 获取最大值,第二大,第三大,第 N 大值

目录 1、原始数据2、获取最大值记录3、获取第二大值记录4、获取第三大值记录 1、原始数据 select * from test_2024_04_15_001 order by 销量 desc,渠道2、获取最大值记录 select 渠道,销量 from ( select a.渠道, a.销量 from test_2024_04_15_001 a order by a.销量 desc,…

Pytorch实用教程:nn.CrossEntropyLoss()的用法

在 PyTorch 中&#xff0c;nn.CrossEntropyLoss() 是一个非常常用且功能强大的损失函数&#xff0c;特别适合用于多类分类问题。这个损失函数结合了 nn.LogSoftmax() 和 nn.NLLLoss() (Negative Log Likelihood Loss) 两个操作&#xff0c;从而在一个模块中提供完整的交叉熵损失…

Spring Boot与Vue联手打造前沿智能学习平台

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

windows下vscode调试虚拟机linux c++工程的三种方法

vscode去远程调试方法有很多种&#xff0c;不同的插件对应了不同的调试方法&#xff0c;比如&#xff1a; 1.C/C插件进行GDB调试(编写launch.json文件) 2.C/C Runner插件 3.CMake Tools插件&#xff08;只针对CMake工程&#xff0c;需要搭配C/C插件一起使用&#xff0c;但无…

【系统分析师】系统测试与维护

文章目录 1、测试方法2、测试阶段3、面向对象的测试4、测试自动化5、软件调试6、软件评审7、软件改进过程8、软件开发环境与工具9、系统转换计划10、系统的运行与维护11、系统审计 1、测试方法 例题 2、测试阶段 注意区分:每个阶段都做了什么事情3、面向对象的测试 4、测试自动…

设计模式之模板方法模式详解(下)

3&#xff09;钩子方法的使用 1.概述 钩子方法的引入使得子类可以控制父类的行为。 2.结构图 3.代码实现 将公共方法和框架代码放在抽象父类中 abstract class DataViewer {//抽象方法&#xff1a;获取数据public abstract void GetData();//具体方法&#xff1a;转换数据…

【传输层】

文章目录 传输层传输服务和协议传输层 vs. 网络层Internet传输层协议多路复用/解复用在发送方主机多路复用在接收方主机多路解复用 多路解复用工作原理无连接&#xff08;UDP&#xff09;多路解复用无连接传输&#xff1a;UDPUDP&#xff1a;用户数据报协议UDP校验和 传输层 目…

华为服务Fellow、首席项目管理专家,华为H5M项目管理标准制定主导者孙虎受邀为PMO大会演讲嘉宾

全国PMO专业人士年度盛会 华为服务Fellow、首席项目管理专家&#xff0c;华为H5M项目管理标准制定主导者孙虎先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“落地项目管理标准&#xff0c;打赢班长的战争”。大会将于5月25-26日在北京举办&am…

excel中vlookup查找值必须在table_array的第一列,有其他办法吗有XLOOKUP

vlookup查找值必须在table_array的第一列&#xff0c;有其他办法吗&#xff1f;有XLOOKUP。 vlookup 查找如下&#xff0c;查找值必须在table_array的第一列 如果下面&#xff0c;编码和名称交换位置&#xff0c;就不能使用vlookup查找了。 XLOOKUP 查找如下

电脑桌面便签软件哪个好?好用的电脑桌面便签

电脑作为我们日常工作的重要工具&#xff0c;承载着大量的任务和项目。当工作任务繁重时&#xff0c;如何在电脑桌面上高效管理这些任务就显得尤为重要。这时&#xff0c;选择一款优秀的桌面便签软件&#xff0c;无疑会给我们带来极大的便利。 一款好的桌面便签软件&#xff0…

注意力机制基本思想(一)

​&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客&#x1f525; 系列专栏&#xff1a; &#x1f3c0;《深度学习基础知识》 相关专栏&#xff1a; ⚽《机器学习基础知识》 &#x1f3d0;《机器学习项目实战》 &#x1f94e;《深度学习项目实战…

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

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