【C++干货基地】面向对象核心概念与实践原理:拷贝构造函数的全面解读

news2024/12/23 13:36:15

在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥 个人专栏: 《C++干货基地》《粉丝福利》

⛺️生活的理想,就是为了理想的生活!

引入

  哈喽各位铁汁们好啊,我是博主鸽芷咕《C++干货基地》是由我的襄阳家乡零食基地有感而发,不知道各位的城市有没有这种实惠又全面的零食基地呢?C++ 本身作为一门篇底层的一种语言,世面的免费课程大多都没有教明白。所以本篇专栏的内容全是干货让大家从底层了解C++,把更多的知识由抽象到简单通俗易懂。

⛳️ 推荐

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

文章目录

  • 引入
  • ⛳️ 推荐
  • 一、拷贝构造函数的引入
    • 1.1 拷贝构造的概念
  • 二、拷贝构造函数的特征
    • 2.1 拷贝构造的书写形式
    • 2.2 不显示定义自动创建
    • 2.3 浅拷贝与深拷贝
    • 2.4 不申请资源不需要显示定义
  • 三、拷贝构造函数调用场景
    • 3.1 使用已存在对象创建新对象
    • 3.2 函数参数类型为类类型对象
    • 3.3 函数返回值类型为类类型对象
  • 📝文章结语:

一、拷贝构造函数的引入

我们都知道面向对象的对象是一个宏观的概念, 万事万物都可以当成一个对象。而现实中我们的对象是可以复制的,那么我们在编程中创建的对象如何进行复制呢?

在这里插入图片描述

1.1 拷贝构造的概念

在C++中祖师爷规定了:当我们想把一个对象赋值给另一个对象的时候

  • 或者创建一个与已存在对象一某一样的新对象
  • 时需要调用它的拷贝函数来进行复制

在这里插入图片描述
如图所见拷贝构造函数是我们的六大成员默认函数之一,构造函数的作用是初始化,析构函数是复制清理工作,而我们的构造拷贝函数是用来同类对象进行赋值给另一个对象时的工作:

二、拷贝构造函数的特征

2.1 拷贝构造的书写形式

讲了怎么长时间拷贝构造是干什么的,下面就来到拷贝构造的创建把:
其实构造的前几个特征是需要先了解才能去书写的所以博主这里把他都给整合到前面了,后面的其他特征单独介绍:

  • 拷贝构造函数是构造函数的一个重载形式
  • 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,
    因为会引发无穷递归调用。

这里第二个特征就特别强调了,我们在书写拷贝构造函数的时候一定要使用传引用

  • 是因为如果我们传值当形参的话那么形参是实参的一份临时拷贝又会拷贝构造函数
  • 这样就会无限递归下去

🍸 代码演示:

class Date
{
public:
 Date(int year = 1900, int month = 1, int day = 1)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 // Date(const Date d)    // 错误写法:编译报错,会引发无穷递归
    Date(const Date& d)    // 正确写法
 {
 _year = d._year;
 _month = d._month;
 _day = d._day;
 }
private:
 int _year;
 int _month;
 int _day;
};
int main()
{
 Date d1;
 Date d2(d1);
 return 0;
}

在这里插入图片描述

  • 所以我们在书写构造函数的时候一定要使用传引用当做形参

2.2 不显示定义自动创建

构造拷贝函数既然是六个默认成员函数之一的话,那么肯定也是符合默认成员函数的特点如果我们没有显示定义的话自动生成:

  • 那么自动生成的拷贝构造函数帮我们完成了什么事情呢?

🍸 代码演示:
在这里插入图片描述

这里我们就可以看到就算我们不写默认成员函数那么编译器也会自动生成 默认拷贝构造函数
去拷贝和赋值,这是可能就有人要问了既然默认生成的 拷贝构造函数 可以完成复制那么为什么要我们手动创建呢?

🔥 这是因为默认生成的拷贝构造函数完成的只是浅拷贝,只是把值复制过去了

2.3 浅拷贝与深拷贝

说到浅拷贝和深拷贝很多铁汁们不太明白,什么是浅拷贝?深拷贝拷贝了那些内容?

  • 下面我们就来看一下这段代码

🍸 代码演示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<stdlib.h>
using namespace std;

class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		_array = (int*)malloc(capacity * sizeof(int));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}

		_size = 0;
		_capacity = capacity;
	}
	void Push(const int& data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	int* _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 对象去进行调用拷贝构造函数进行拷贝:

  • 而这里只进行了浅拷贝,在 S2 进行拷贝构造的时候只是简单的把值复制过去了
  • 所以 S2 和 S1 是指向同一块空间并没有给 S2 去单独开辟一个一模一样的空间

这里就是我们说的浅拷贝,S2 和 S1 指向用一块空间而当程序结束的时候 S2 调用它的析构函数去吧 S1 所指向的空间给释放了, 那么当 S1 在释放的时候就重复释放了原来释放的空间导致程序崩溃。

在这里插入图片描述

🔥 所以在这些去动态申请资源的函数的类去,一定要显示定义拷贝构造函数进行深拷贝

  • 把空间大小和值(内容)完全拷贝进去
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<stdlib.h>
using namespace std;

class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		_array = (int*)malloc(capacity * sizeof(int));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}

		_size = 0;
		_capacity = capacity;
	}
	Stack(const Stack& p1)
	{
		int* tmp = (int*)malloc(sizeof(int) * p1._capacity);
		if (tmp == nullptr)
		{
			perror("file malloc");
			exit(-1);			

		}

		memcpy(tmp, p1._array, sizeof(int) * p1._size);

		_array = tmp;
		_capacity = p1._capacity;
		_size = p1._size;
		
	}
	void Push(const int& data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	int* _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;
}


2.4 不申请资源不需要显示定义

如果我们一个类里面并不会去申请资源那么它的默认生成的拷贝构造函数 ,也就够用了。默认生成的拷贝构造函数只会进行值拷贝而我们在不申请资源的话,值拷贝就是我们需要的功能。

  • 🔥 注:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请
    时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

三、拷贝构造函数调用场景

到了这里我相信大家一定对靠北构造函数有一定认知了那么大家知道拷贝函数在哪些场景会自动调用呢?

3.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;
};

int main()
{
 Date d1(2022,1,13);
 Test(d1);
 return 0;
}

3.2 函数参数类型为类类型对象

在以前学习函数的时候我们知道,形参是实参的一份临时拷贝所以当函数参数类型为 类 的类型对象的话也会自动调用 拷贝构造函数

🍸 代码演示:

Date Test(Date d)
{
 Date temp(d);
 return temp;
}

3.3 函数返回值类型为类类型对象

函数的返回值返回给我们调用的对象时候,返回的是 temp 的一份临时拷贝并不是对象本身

🍸 代码演示:

Date Test(Date d)
{
 Date temp(d);
 return temp;
}

📝文章结语:

☁️ 看到这里了还不给博主扣个:
⛳️ 点赞🍹收藏 ⭐️ 关注
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!

在这里插入图片描述

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

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

相关文章

Learn OpenGL 07 摄像机

定义摄像机参数 glm::vec3 cameraPos glm::vec3(0.0f, 0.0f, 3.0f);//摄像机位置glm::vec3 cameraTarget glm::vec3(0.0f, 0.0f, 0.0f);glm::vec3 cameraDirection glm::normalize(cameraPos - cameraTarget);//摄像机方向&#xff0c;指向z轴正方向 glm::vec3 up glm::vec…

套接字编程 --- 三

目录 1. 前置性知识 1.1. listen 系统调用 1.2. accept 系统调用 1.3. 如何通信 1.3.1. read 系统调用 && write系统调用 1.3.2. recv 系统调用 && send 系统调用 2. TCP --- demo 2.1. Tcp_Server.hpp (version 1) 2.2. Tcp_Server.hpp (version 2…

[AIGC] Kafka解析:分区、消费者组与消费者的关系

Apache Kafka是一个分布式事件流平台&#xff0c;它是处理实时数据的强大工具。而理解Kafka的关键概念&#xff1a;分区&#xff08;Partition&#xff09;、消费者组&#xff08;Consumer Group&#xff09;和消费者&#xff08;Consumer&#xff09;的关系对于正确地使用Kafk…

C语言--- 指针运算笔试题详解

目录 题目1&#xff1a; 题目2&#xff1a; 题目3&#xff1a; 题目4&#xff1a; 题目5&#xff1a; 题目6&#xff1a; 题目7&#xff1a; 题目1&#xff1a; #include <stdio.h> int main() {int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(&a 1);print…

C#与WPF通用类库

个人集成封装&#xff0c;仓库已公开 NetHelper 集成了一些常用的方法&#xff1b; 如通用的缓存静态操作类、常用的Wpf的ValueConverters、内置的委托类型、通用的反射加载dll操作类、Wpf的ViewModel、Command、Navigation、Messenger、部分常用UserControls(可绑定的Passwo…

蓝桥杯-ISBN号码

此题然让本人纠结了很久&#xff0c;真的好多坑。。。。果然还是太菜了。 完整代码以及思路解析(在注释中) #include <iostream> using namespace std; int main() {string num;cin>>num; int count0;int w1;for(int i0;i<10;i){if((i!1)&&(i!5)) //坑…

Node.js作用

Node.js可以开发应用 开发服务器应用 开发工具类应用 开发桌面端应用

Discord OAuth2授权以及机器人监听群事件

下面文章讲解获取OAuth2授权整个流程&#xff0c;创建机器人&#xff0c;使用机器人监听工会&#xff08;工会就是创建的服务器&#xff09;成员变化等等&#xff0c;对接国外的都是需要VPN的哦&#xff0c;对接的时候记得提前准备。 创建应用 点击 此页面添加应用,&#xff…

EI级 | Matlab实现GCN基于图卷积神经网络的数据多特征分类预测

EI级 | Matlab实现GCN基于图卷积神经网络的数据多特征分类预测 目录 EI级 | Matlab实现GCN基于图卷积神经网络的数据多特征分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.GCN基于图卷积神经网络的数据分类预测 Matlab2023 2.多输入单输出的分类预测&#xf…

汽车电子:均胜电子、德赛西威“跑出”第二增长曲线

问界新M7上市以来销量势如破竹&#xff0c;华为汽车及相关均胜电子、联创电子、光峰科技等供应链企业也因此受益。 网络公开数据&#xff0c;在2024年1月1日-2月18日&#xff0c;中国市场新势力品牌销量排行榜中&#xff0c;问界就以4.25万辆的销量成绩霸榜第一&#xff0c;作…

幻兽帕鲁Palworld服务器搭建费用,仅需26元!

2024阿里云幻兽帕鲁专用服务器价格表&#xff1a;4核16G幻兽帕鲁专用服务器26元一个月、149元半年&#xff0c;默认10M公网带宽&#xff0c;8核32G幻兽帕鲁服务器10M带宽价格90元1个月、271元3个月。阿里云提供的Palworld服务器是ECS经济型e实例&#xff0c;CPU采用Intel Xeon …

政务网站安全合规之道,云监测提供优质监测解决方案

近年来&#xff0c;国家对于网站安全风险的问题重视程度不断提升&#xff0c;持续加强对网站安全的监管力度。特别是政务网站&#xff0c;承载着越来越重要的核心应用和数据&#xff0c;与普通网站相比更容易遭到来自互联网的攻击。 攻击者为了破坏政务形象、干扰政务工作秩序或…

RC4算法:流密码算法的经典之作

title: RC4算法&#xff1a;流密码算法的经典之作 date: 2024/3/11 18:16:16 updated: 2024/3/11 18:16:16 tags: RC4起源演变算法优劣分析RC4 vs AES安全性RC4 vs DES性能比较应用场景介绍工作原理详解代码实例演示 一、RC4算法的起源与演变 RC4算法是由著名密码学家Ron Riv…

Oracle数据库迁移至达梦8数据库(windows图文讲解)

写作不易&#xff0c;如果对各位有用请给个赞支持一下~ 1.第一步安装达梦8数据库&#xff1a; 下载安装看我这篇博客 https://blog.csdn.net/li836779537/article/details/136641411?spm1001.2014.3001.5502 2.废话不多说直接开干&#xff0c;安装完成后打开迁移工具 名字…

指令微调(Instructional Fine-tuning)

定义 指令微调&#xff08;Instructional Fine-tuning&#xff09;是一种自然语言处理&#xff08;NLP&#xff09;技术&#xff0c;特别是在大型预训练语言模型&#xff08;如 GPT、BERT 等&#xff09;的应用中。在指令微调中&#xff0c;模型被进一步训练以更好地理解和遵循…

Linux--ELK 日志分析系统

ELK &#xff08;Elasticsearch、Logstash、Kibana&#xff09;日志分析系统的好处是可以集中查看所有服务器日志&#xff0c;减轻了工作量&#xff0c;从安全性的角度来看&#xff0c;这种集中日志管理可以有效查询以及跟踪服务器被攻击的行为。 > Elasticsearch 是个开源分…

容器安全是什么?

容器安全定义 容器安全是指保护容器的完整性。这包括从其保管的应用到其所依赖的基础架构等全部内容。容器安全需要完整且持续。通常而言&#xff0c;企业拥有持续的容器安全涵盖两方面&#xff1a; 保护容器流水线和应用保护容器部署环境和基础架构 如何将安全内置于容器流…

[BUG] docker运行Java程序时配置代理-Dhttp.proxyHost后启动报错

[BUG] docker运行Java程序时配置代理-Dhttp.proxyHost后启动报错 bug现象描述 版本&#xff1a;2.0.4&#xff08;客户端和服务端都是&#xff09; 环境&#xff1a;私有云环境&#xff0c;只有少量跳板机器可以访问公网&#xff0c;其他机器均通过配置代理方式访问公网 bug现…

CSS中grid网格布局详解

文章目录 一、是什么二、属性display 属性grid-template-columns 属性&#xff0c;grid-template-rows 属性grid-row-gap 属性&#xff0c; grid-column-gap 属性&#xff0c; grid-gap 属性grid-template-areas 属性grid-auto-flow 属性justify-items 属性&#xff0c; align-…

数据结构 之 链表LinkedList

目录 1. ArrayList的缺陷&#xff1a; 2. 链表&#xff1a; 2.1 链表的概念及结构&#xff1a; 3. 链表的使用和模拟实现&#xff1a; 3.1 构造方法&#xff1a; 3.2 模拟实现&#xff1a; 4. 源码分享&#xff1a; 在我学习顺序表之后&#xff0c;我就立马开始了链表的学…