拷贝构造函数详解

news2025/7/27 21:43:37

拷贝构造函数详解

  • 1.概念与特征
  • 2.浅拷贝
  • 3.深拷贝
  • 4.拷贝构造函数典型调用场景:

如果一个类中什么成员都没有,那么该类简称为空类。而空类中其实并不是真的什么都没有,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

  • 构造函数:主要完成初始化工作
  • 析构函数:主要完成资源的清理工作
  • 拷贝构造函数:主要用于使用同类对象初始化创建对象
  • 赋值运算符重载:主要是把一个对象赋值给另一个对象
  • 普通对象取地址重载
  • const对象取地址重载(取地址重载很少会自己实现)

本篇文章,我们来学习拷贝构造函数。

1.概念与特征

概念:

若未显式定义,编译器会生成默认的拷贝构造函数。拷贝构造函数只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

特征:

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

  1. 拷贝构造函数是构造函数的一个重载形式。
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	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.浅拷贝

默认的拷贝构造函数对象按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

class Time
{
public:
	Time()
	{
		_hour = 1;
		_minute = 1;
		_second = 1;
	}
	
	Time(const Time& t)
	{
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
		cout << "调用了Time类的拷贝构造函数" << endl;
	}
	
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
private:
	// 基本类型(内置类型)
	int _year = 1970;
	int _month = 1;
	int _day = 1;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d1;
	// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
	// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数
	Date d2(d1);
	return 0;
}

在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的。

3.深拷贝

编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝(浅拷贝)了,还需要自己显式实现吗?当然像日期
类这样的类是没必要的。那么下面的类呢?验证一下试试?

typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		DateType* _array = (DataType*)malloc(capacity * sizeof(DataType));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_size = 0;
		_capacity = 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;
}

在这里插入图片描述
默认生成的拷贝构造函数对内置类型的处理和自定义类型的处理是不同的。

对自定义类型的成员,会去调用该成员的拷贝构造

对于内置类型的成员会完成浅拷贝(值拷贝,按字节拷贝),但是浅拷贝存在着很严重的问题,如果内置类型成员有指针(涉及对资源的管理),那么在浅拷贝的时候相当于把地址也按字节复制过去了,此时两个对象的指针就会指向同一块空间,这时,修改这片空间的数据就会相互影响,且这块空间析构时会释放两次,程序会崩溃。

为了解决浅拷贝的这个问题,我们需要自己实现拷贝构造函数来完成深拷贝。

类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要自己写的,以完成深拷贝,否则就是浅拷贝,不仅在修改数据时会相互影响,还会导致重复释放,会造成程序崩溃。

4.拷贝构造函数典型调用场景:

  • 使用已存在对象创建新对象
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象
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.coloradmin.cn/o/16581.html

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

相关文章

对GROUP BY的增强

使用ROLLUP操作产生求和值使用CUBE操作产生使用GROUPING函数确定该行值是由ROLLUP或者CUBE创建的使用GROUPING SETS生成一个简单的结果集[oracleoracle-db-19c ~]$ [oracleoracle-db-19c ~]$ sqlplus / as sysdbaSQL*Plus: Release 19.0.0.0.0 - Production on Fri Nov 18 10:…

idea2022.2.3版本下载安装配置(包含运行第一个java程序教程)详细步骤

目录 一、下载idea 1.去浏览器搜索idea官网&#xff0c;找到官网 2.选择Download 3.点击左边的Download下载就好了 4.在本地磁盘建一个文件夹&#xff0c;专门用来存放idea软件的 二、安装idea 5.在本地磁盘中的下载里面找到下载的idea并双击打开 6.选择Next ​编辑 7…

【无标题】PCIe收发卡设计资料原理图:611-基于VU9P的2路4Gsps AD 2路5G DA PCIe收发卡

基于VU9P的2路4Gsps AD 2路5G DA PCIe收发卡一、板卡概述 基于XCVU9P的5Gsps AD DA收发PCIe板卡。北京太速科技该板卡要求符合PCIe 3.0标准&#xff0c;包含一片XCVU9P-2FLGA2014I、2组64-bit/8GB DDR4、2路高速AD&#xff0c; 2路高速DA&#xff0c;支持外触发&#xff…

基于单片机的学生视力保护仪

目录 摘 要 1 ABSTRACT 2 第一章 绪论 4 1.1课题的选题背景 4 1.2国内外发展现状 5 1.3本论文主要研究内容 6 1.3.1主要内容 6 1.3.2基本要求 7 第二章 学生视力保护仪总系统设计 8 2.1系统总框图 8 2.2单片机的选择 8 2.3传感器的选择 9 2.4编程语言的选择 9 第三章 系统硬件…

CentOS 7 源码制作ngnx-1.22.1-ipv6 rpm —— 筑梦之路

源码包&#xff1a;http://nginx.org/packages/centos/7/SRPMS/nginx-1.22.1-1.el7.ngx.src.rpm # 安装依赖包yum install http://mirror.centos.org/centos/7/os/x86_64/Packages/pcre2-devel-10.23-2.el7.x86_64.rpm# 安装源码包 初始化项目rpm -ivh nginx-1.22.1-1.el7.ngx…

5G无线技术基础自学系列 | 物理下行控制信道

素材来源&#xff1a;《5G无线网络优化实践》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 2.4.1 PDCCH位置定义 在LTE中&#xff0…

ESP32的AP模式使用

WifiClient 和WebServe有啥区别? (14 封私信 / 1 条消息) httpclient 和webservice有啥区别? - 知乎 (zhihu.com) 1.Webservice两大核心&#xff1a;soap&#xff08;理解为要传输的数据&#xff09;、wsdl&#xff08;理解为传输数据xml的说明&#xff09; soap xml ht…

Java类变量和类方法(static)

文章目录类变量-提出问题类变量内存布局如何定义类变量如何访问类变量类变量使用细节类方法介绍类变量-提出问题 提出问题的主要目的就是让大家思考解决之道&#xff0c;从而引出我要讲的知识点. 说:有一群小孩在玩堆雪人,不时有新的小孩加入&#xff0c;请问如何知道现在共有…

客服系统Golang源码

客服系统 概述 采用Golang语言&#xff0c;基于 gRPC [Mongo Vue3WebsocketRabbitMQ]来实现系统 用户侧逻辑采用匿名注册模式&#xff0c;Token采用JWT技术&#xff0c;服务端不保存Token信息&#xff0c;用户每次使用检测Token合法时返回新的Token来达到续期的目的 后端分…

kubernetes集群基于kubeadm部署以及常见问题解决

文章目录集群类型主机规划环境初始化检查操作系统版本关闭防火墙设置主机名主机名解析时间同步关闭 SELinux关闭 swap 分区将桥接的IPv4流量传递到iptables的链开启ipvs安装容器运行时&#xff08;Docker&#xff09;卸载Docker旧版本&#xff1a;安装 gcc 相关安装Docker设置阿…

Vivado_AXI Quad SPI_IP核

填一下前面的坑。 介绍关于Vivado中AXI Quad SPI v3.2的使用方法。 参考资料&#xff1a;pg153-axi-quad-spi.pdf&#xff0c;可自行在官网下载。 以该IP核的Standard SPI Mode的使用为例。 Address Space OffsetRegister NameAccess TypeDefault Value (hex)Description40hS…

【JavaSE】抽象类

前言&#xff1a; 作者简介&#xff1a;爱吃大白菜1132 人生格言:纸上得来终觉浅&#xff0c;绝知此事要躬行 如果文章知识点有错误的地方不吝赐教&#xff0c;和大家一起学习&#xff0c;一起进步&#xff01; 如果觉得博主文章还不错的话&#xff0c;希望三连支持&#xff01…

知物由学 | 弹幕蜂拥而入,智能审核平台如何用技术破局?

导读&#xff1a;弹幕的出现增加了视频观看者的深度参与感&#xff0c;弹幕也逐渐成为国内各大视频网站最基本的评论交互形式&#xff0c;本文将通过网易易盾在弹幕实现原理及交互方式方面的实践&#xff0c;具体介绍弹幕相较于传统聊天室的区别与实践经验&#xff0c;希望能为…

【检索资讯】2022年控制理论与应用国际会议(ICOCAT 2022)已成功被EI检索

ICOCTA 2022&#xff08;www.icocta.org&#xff09; 2022年控制理论与应用国际会议&#xff08;ICOCAT 2022&#xff09;已成功被EI&#xff0c;Scopus检索&#xff0c;作者可自行登录EI数据库查询检索&#xff0c; ICOCTA 2023会议预告 重要信息 会议官网&#xff1a;www.i…

新品速看丨创新微MinewSemi正式推出GNSS高精度卫星定位导航模块

致力于GNSS、蓝牙、Wi-Fi、LoRa、UWB等物联网无线模块研究的一站式供应商——创新微MinewSemi近日推出了数款基于多种卫星导航授时、多星多频、具有低功耗、高灵敏度、抗干扰、高性能的工业级GNSS高精度定位模块。 此次推出的GNSS模块各有特点&#xff0c;满足用户不同需求&…

【LeetCode】用队列实现栈和用栈实现队列(C语言)

目录 1.用队列实现栈 增删 求栈顶元素 判断栈为空 2.用栈实现队列 增删 返回队列开头的数据 判断队列为空 尾言 源码 队列实现栈 栈实现队列 刚讲完栈和队列&#xff0c;LeetCode上有两题栈与队列的互相实现&#xff0c;简单地讲讲思路和实现吧。 1.用队列实现栈 原题地址&am…

婴幼儿蛋白质过敏怎么回事

很多孩子吃了含蛋白质的食物后会出现瘙痒或痱子等过敏症状&#xff0c;甚至全身发红。这是因为一些过敏体质的孩子儿童会对蛋白质过敏。婴儿蛋白质过敏会导致一些严重的问题&#xff0c;那么当婴儿蛋白质过敏发生时&#xff0c;该怎么以下是一个详细的介绍&#xff01;目录蛋白…

[Spring Boot]08 IDEA接入MyBatisCodeHelper代码自动生成器

目录前言一、插件市场安装插件二、使用插件自动生成代码前言 上次介绍了&#xff0c;原生mybatis的方法&#xff1a; 06 Spring Boot接入mybatis通用mapper插件自动生成器。 这次&#xff0c;再介绍下插件MyBatisCodeHelper-Pro的用法&#xff0c;使用此方法更加简单和方便。 …

老照片修复工具哪个好?这几个修复软件你快看看

相信我们很多小伙伴的爷爷奶奶家里都会有很多老照片&#xff0c;这些照片由于年代久远&#xff0c;或多或少都会有些损坏&#xff0c;不是泛黄就是有些褶皱&#xff0c;如果我们想将照片进行流传下去&#xff0c;肯定就是将其修复并重新洗出来啦。要是不想出门找专业的摄影师修…

Spring Boot 整合 MyBatis Plus实现多数据源的两种方式

第一种&#xff1a;使用配置类的方式&#xff1a; 项目结构 xml依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-ins…