类的默认成员函数——拷贝构造函数

news2024/11/23 21:25:26

1.概念引入

在现实生活中,如果有两个兄弟长得一模一样,我们就称其为双胞胎

 当我们创建了一个新的对象,需要用同类型的对象拷贝并初始化,就要用到拷贝构造函数

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

2.特征

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);//或者写成 Date d2 = d1;
	return 0;
}

3.若未显示定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储,按字节序完成拷贝,这种拷贝叫浅拷贝,或者值拷贝。与之相应的叫做深拷贝

在下面这个案例中,用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数,但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数 

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::Time(const 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;
	Date d2(d1);
	return 0;
}

下面对浅拷贝和深拷贝分别做一个简单的介绍

浅拷贝

  • 浅拷贝仅仅复制对象的第一层属性。
  • 对于基本数据类型(如数字、字符串、布尔值等),浅拷贝会直接复制其值
  • 对于引用类型(如数组、对象等),浅拷贝不会复制引用类型数据本身,而是复制引用的地址。这意味着原始对象和拷贝对象在引用类型数据上共享同一块内存地址。
  • 因此,如果修改原始对象的引用类型属性,拷贝对象的相应属性也会受到影响。

深拷贝: 

  • 深拷贝会复制对象的所有属性,包括嵌套的引用类型数据。
  • 对于基本数据类型,深拷贝同样复制其值
  • 对于引用类型,深拷贝会创建一个新的对象,并递归地复制原始对象中引用类型数据的所有属性,从而在内存中创建一个全新的副本
  • 这意味着原始对象和拷贝对象在内存中是完全独立的,修改拷贝对象不会影响原始对象。

对比:

  • 内存独立性:深拷贝产生的对象在内存中是完全独立的,而浅拷贝产生的对象在引用类型数据上与原始对象共享内存。
  • 修改影响:修改深拷贝对象的属性不会影响原始对象,而修改浅拷贝对象的引用类型属性会影响原始对象。
  • 性能开销:深拷贝通常比浅拷贝更耗时,因为它需要递归复制所有嵌套的对象。
  • 适用场景:如果需要完全独立的数据副本,应该使用深拷贝;如果只需要复制顶层属性,或者原始对象不会改变,可以使用浅拷贝。 

案例:栈的深拷贝 

Stack(const Stack& st)
{
	_array = (DataType*)malloc(sizeof(DataType*) * st._capacity);
	if (NULL == _array)
	{
		perror("malloc申请空间失败");
		return;
	}
	memcpy(_array, st._array, sizeof(DataType) * st._size);
	_size = st._size;
	_capacity = st._capacity;
}

4.类中如果没有涉及资源申请,拷贝构造函数是否写都可以;但是一旦涉及到资源申请,拷贝构造函数是一定要写的,否则就是浅拷贝

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

  • 使用已存在对象创建新对象
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象

 综合案例分析

#include<iostream>
using namespace std;
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(2024, 6, 25);
	Test(d1);
	return 0;
}

由以上案例可以看出,传值传参会调用拷贝构造,所以为了提高程序的效率,返回时根据实际场景,能用引用尽量使用引用 

4.总结

  • 如果没有管理资源,一般情况下就不需要写拷贝构造,默认生成的拷贝构造就可以,比如日期类
  • 如果都是自定义类型成员,内置类型成员没有指向资源,也是使用默认生成的拷贝构造即可,如MyQueue
  • 一般情况下,不需要显式写析构,就不用写拷贝构造
  • 如果内部有指针或一些值指向资源,需要显式写析构,通常就需要显式写构造完成深拷贝,如:Stack,Queue,List 

拷贝构造函数也比较抽象,希望大家看完本文有所收获

点赞收藏关注是博主不断更新优质好文的动力哦~  

 

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

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

相关文章

2024 年 8 款最佳建筑 3D 渲染软件

你现在使用的3D 渲染软件真得适合你吗&#xff1f; 在建筑和室内渲染当中&#xff0c;市面上有许多3D渲染软件可供选择。然而&#xff0c;并不是每款软件都适合你的需求。本指南将重点介绍2024年精选的8款最佳建筑3D渲染软件&#xff0c;帮助你了解不同的选项&#xff0c;并选…

STM32的SPI通信

1 SPI协议简介 SPI&#xff08;Serial Peripheral Interface&#xff09;协议是由摩托罗拉公司提出的通信协议&#xff0c;即串行外围设备接口&#xff0c;是一种高速全双工的通信总线。它被广泛地使用在ADC、LCD等设备与MCU间&#xff0c;使用于对通信速率要求较高的场合。 …

基于Java的宠物领养管理系统【附源码】

摘 要 近些年来&#xff0c;随着科技的飞速发展&#xff0c;互联网的普及逐渐延伸到各行各业中&#xff0c;给人们生活带来了十分的便利&#xff0c;宠物管理系统利用计算机网络实现信息化管理&#xff0c;使整个宠物领养的发展和服务水平有显著提升。 本文拟采用IDEA开发工具…

Live Wallpaper Themes 4K Pro for Mac v19.9 超高清4K动态壁纸

Live Wallpaper & Themes 4K Pro for Mac v19.7 是一款专为Mac用户设计的超高清4K动态壁纸应用程序。它凭借出色的视觉效果和丰富的个性化设置&#xff0c;为用户带来全新的桌面体验。 这款软件提供了大量精美的动态壁纸供用户选择&#xff0c;涵盖了各种风格和主题&#…

考个嵌入式中级证书吧,有大用!

随着物联网、人工智能的蓬勃发展&#xff0c;嵌入式行业迎来了前所未有的发展机遇&#xff1a;物联网的万物互联需求&#xff0c;为嵌入式系统开拓了广阔的应用场景&#xff1b;人工智能的融入促使嵌入式设备向更智能、更自主的方向进化。然而&#xff0c;行业的火爆&#xff0…

都2024年了,现在互联网行情怎样?

都2024年了&#xff0c;互联网行情是怎样的&#xff1f; 很直白的说&#xff0c;依旧是差得很&#xff0c;怎么说&#xff1f; 我刚在掘金上看到一个掘友写的文章&#xff0c;他是四月领了大礼包&#xff0c;据他的描述如下&#xff1a; 互联网行情依旧是差得很&#xff0c;很…

通过迭代器删除容器中的元素

通过之前的介绍我们知道通过迭代器来遍历单例集合的操作仍然需要借助于循环结构。而且我们知道在单例集合中调用iterator方法返回的Iterator对象中还有一个remove方法我们没有介绍&#xff0c;它的作用是删除容器中的元素。说道这里应该有人会发现一个很明显的问题&#xff0c;…

第28课 绘制原理图——绘制导线

概述 放置完元器件之后&#xff0c;接着就要用导线将元器件的管脚一个一个连起来了。 绘制导线的方法 点击快速工具条上的“线”命令&#xff0c;进入绘制导线的过程。 点击选择某个管脚或电源端口&#xff0c;作为导线的起始端。 再点击选择另一个管脚或电源端口&#xff0c…

MT6989(天玑9300)芯片性能参数_MTK联发科5G处理器

MT6989是联发科Dimensity旗舰系列的成员&#xff0c;旨在为旗舰5G智能手机供应商提供最先进的技术和性能。MT6989也是联发科目前最具创新和强大的5G智能手机芯片&#xff0c;具有领先的功耗效率&#xff0c;无与伦比的计算架构&#xff0c;有史以来最快和最稳定的5G调制解调器&…

动物常见图像的图像分类数据集

常见动物图像分类数据集 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1zZnCUZuNlX6MjuZImlDjTw?pwd03b9 提取码&#xff1a;03b9 数据集信息介绍&#xff1a; 文件夹 大象 中的图片数量: 1446 文件夹 松鼠 中的图片数量: 1862 文件夹 河马 中的图片数量:…

YOLOv8/v10项目使用教程

根据改好的YOLOv8.yaml改yolov10.yaml教程 打开ultralytics/cfg/models/v8路径&#xff0c;找到需要移植的yaml文件&#xff0c;从其中复制相关的模块。打开一个YOLOv10的yaml文件。 注释掉之前相应位置的模块&#xff0c;并粘贴上面复制的模块&#xff0c;完成。 其余使用步骤…

upload-labs第14关

upload-labs第14关 第十四关一、源代码分析代码审计 二、绕过分析a. 制作图片码首先需要一个照片&#xff0c;然后其次需要一个eval.php。 b.上传图片码上传成功 c.结合文件包含漏洞进行访问访问&#xff1a;http://192.168.1.110/upload-labs-master/include.php?filehttp://…

SNEC天合储能秀:全球首发多元场景一站式工商业储能融合解决方案

6月13日-15日&#xff0c;SNEC2024光伏与智慧能源展在上海隆重举行&#xff0c;来自全球95个国家和地区3000家国内外展商齐聚展会&#xff0c;5000行业专家共话产业发展。致力于成为全球光储智慧能源解决方案的领导者&#xff0c;天合光能&#xff08;展位号&#xff1a;7.2H-E…

LiveMedia视频汇聚平台的设备管理功能

LiveMedia视频汇聚平台的设备管理功能是实现视频资源有效管理和控制的关键组成部分。以下是设备管理功能的详细介绍&#xff1a; 设备接入与管理&#xff1a; 设备添加与编辑&#xff1a;平台支持添加、编辑与删除设备&#xff0c;可编辑的信息包括设备接入的协议类型、服务节…

ICASSP论文结构研究

MLCA-AVSR 基于多层交叉注意融合的视听语音识别 ABSTRACT 目标任务现状、目前研究现状(研究大方向、研究的欠缺)、本文方法、方法效果(排名、分数) 有一个Index Terms INTRODUCTION 目标任务的简单发展历程与发展现状&#xff0c;目前任务的难点&#xff0c;指出为什么会…

代码随想录-Day39

62. 不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&…

Gradle学习-2 Groovy

1、Groovy基础语法 1.1、基本数据类型 Groovy支持数据类型&#xff1a;byte, short, int, long, float, double, char &#xff08;1&#xff09;创建一个Android Studio项目 &#xff08;2&#xff09;在根目录新建一个 leon.gradle&#xff0c;输入以下内容 leon.gradle…

Netty学习(二)——黏包半包、协议设计解析、聊天室

一、粘包与半包 1.1 粘包和半包复现 1、粘包复现&#xff1a; Server代码&#xff1a; public class ProblemServer {public static void main(String[] args) throws InterruptedException {new ServerBootstrap()//若是指定接收缓冲区大小&#xff1a;就会出现黏包、半包…

计算机基础知识——面向对象:封装+继承+多态整理

面向对象三大特性&#xff1a;封装、继承、多态。 1.封装 将一系列相关事物的共同的属性和行为提取出来&#xff0c;放到一个类中&#xff0c;同时隐藏对象的属性和实现细节&#xff0c;仅对外提供公共的访问方式。 【JavaBean类就可以看作是封装的完美案例。】 setter和get…

电磁兼容试验数据的单位转换 笔记

1. 单位dB 的介绍 分贝&#xff08;decibel&#xff0c;/dɛsɪ.bɛl/&#xff09;是量度两个相同单位之数量比例的计量单位&#xff0c;主要用于度量声音强度&#xff0c;常用dB表示。 分贝是较常用的计量单位。可表示为&#xff1a; 1. 表示功率量之比的一种单位&#xff0c…