当前位置: 首页 > news >正文

C++中类的6个默认成员函数 【拷贝构造函数】

文章目录

    • 拷贝构造函数的使用
      • 拷贝构造对于自定义类型【浅拷贝】
      • 深拷贝
      • 拷贝构造函数典型调用场景

拷贝构造函数的使用

  • 在前几章学习对象的时候,我们有的时候需要一个与已存在对象一某一样的新对象

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

  • 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用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) // 错误写法:编译报错,会引发无穷递归Date(const Date& d) // 必须传引用{_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2024,2,1);Date d2(d1);return 0;
}

在这里插入图片描述

  • 下面我们解释一下:
  • 这里的const可加可不加,但是建议加上
  • 有些人就写这个写昏头了,写反了,不加const的话不会提示

在这里插入图片描述

  • 加上了就知道哪里错了,所以还是加上较好

在这里插入图片描述

  • 这里的拷贝构造必须传引用,要不然会引发无穷递归【反正编译会报错~】

在这里插入图片描述

  • 再看下面代码,我是没有写拷贝构造的,但是这里自动拷贝了,毕竟这个是默认成员函数,这里生成的还和之前几个的默认成员函数还不一样,之前的对默认成员函数对内置类型不处理,而这个拷贝构造对内置类型处理了,如果没有处理,这里就拷贝不出来
  • 说明这里会自动生成一个拷贝构造函数,将值拷贝回去
  1. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝
class Date
{
public:// 构造函数Date(int year = 2024, int month = 2, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2024, 2, 1);Date d2(d1);d1.Print();d2.Print();return 0;
}

在这里插入图片描述

拷贝构造对于自定义类型【浅拷贝】

  • 那么对于自定义类型呢?
class Time
{
public: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
{
public:Date(int year = 2024, int month = 2, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day;// 自定义类型Time _t;
};
int main()
{Date d1(2024,2,1);Date d2(d1);d1.Print();d2.Print();return 0;
}

在这里插入图片描述

  • 我们有一个方法就是强制让编译器生成

  • 加上这一条:

Time() = default;

在这里插入图片描述

深拷贝

  • 刚刚上面的一种场景叫做浅拷贝,还有一个场景就是深拷贝

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

  • 下面我这个代码没有写拷贝构造,它会自动生成一个默认的值拷贝,我们来运行一下

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_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;
}
  • 我们看到程序崩溃了~~

在这里插入图片描述

  • 也就是在一些场景下,默认生成的拷贝构造是会出事的

  • 再调试看一下:

在这里插入图片描述

  • 这会导致两个对象指向同一块空间

在这里插入图片描述

  • 在结束的时候会调用析构函数,会把那块空间给释放了

在这里插入图片描述

  • 再次释放的时候会出现错误
  • 同一块空间被释放了两次【所以是绝对不能的】

在这里插入图片描述

  • 正确的我们这样写
  • 需要引入一个叫做深拷贝
Stack(const Stack& s)
{// 深拷贝DataType* tmp = (DataType*)malloc(s._capacity * sizeof(DataType));if (nullptr == tmp){perror("malloc fail\n");exit(-1);}memcpy(tmp, s._array, sizeof(DataType) * s._size);_array = tmp;// 浅拷贝_size = s._size;_capacity = s._capacity;
}

在这里插入图片描述

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

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

  • 使用已存在对象创建新对象
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象
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;
}

在这里插入图片描述

  • 为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。

最后本文就到这里结束了,感谢大家的收看,请多多指点~

相关文章:

C++中类的6个默认成员函数 【拷贝构造函数】

文章目录 拷贝构造函数的使用拷贝构造对于自定义类型【浅拷贝】深拷贝拷贝构造函数典型调用场景 拷贝构造函数的使用 在前几章学习对象的时候&#xff0c;我们有的时候需要一个与已存在对象一某一样的新对象 那在创建对象时&#xff0c;可否创建一个与已存在对象一某一样的新对…...

【前端高频面试题--Vuex下篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;前端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac;前端高频面试题--Vuex篇 往期精彩内容Vuex 的原理Vuex中action和mutation的区别Vuex 和 localStor…...

MySQL性能调优篇(4)-查询语句的优化与重构

MySQL数据库查询语句的优化与重构 MySQL是一种常用的关系型数据库管理系统&#xff0c;广泛应用于Web开发中。在实际应用中&#xff0c;对数据库查询语句的优化和重构是提高应用性能和响应速度的重要手段。本文将介绍一些常见的优化技巧和重构方法&#xff0c;帮助开发者提高数…...

LInux、源码编译安装

步骤&#xff1a; 步骤1&#xff1a;安装开发工具gcc与make&#xff0c;释放源代码至指定目录 yum -y install gcc make 步骤2&#xff1a;tar解包&#xff0c;释放源代码至指定目录 tar -xf /root/tools.tar.gz -C /usr/local 步骤3&#xff1a;./configure 配置&#xff0c;…...

wordpress好的网站主题

有什么好的网站主题&#xff0c;都分享在这里了。 蓝色风格的wordpress模板&#xff0c;好的wordpress网站主题&#xff0c;需要既好看&#xff0c;又好用。 https://www.zhanyes.com/qiye/6305.html 血红色的好看的wordpress主题&#xff0c;布局经典&#xff0c;设计好的&am…...

【Java多线程】对进程与线程的理解

目录 1、进程/任务&#xff08;Process/Task&#xff09; 2、进程控制块抽象(PCB Process Control Block) 2.1、PCB重要属性 2.2、PCB中支持进程调度的一些属性 3、 内存分配 —— 内存管理&#xff08;Memory Manage&#xff09; 4、线程&#xff08;Thread&#xff09;…...

C# CAD交互界面-自定义面板集-查找定位(六)

运行环境 vs2022 c# cad2016 调试成功 一、代码说明 1. 类成员变量声明&#xff1a; List<ObjectId> objectIds new List<ObjectId>(); // 用于存储AutoCAD实体对象的ObjectId列表 private static Autodesk.AutoCAD.Windows.PaletteSet _ps2; // 自定义浮动面板…...

5.7 BCC工具之disksnoop.py解读

一,disksnoop.py简介 disksnoop工具用于追踪块设备的I/O操作的延迟,它会在每次I/O执行完成后打印一行摘要信息。我们根据这些摘要日志,来分析当前的I/O操作是否存在延迟,以判断I/O是否达到了瓶颈。 二,代码示例 #!/usr/bin/python # # disksnoop.py Trace block device…...

QT:实现图片选择器

一、效果图 二、用到的类 qApp&#xff1a;可以快速获取到项目目录位置。 QSettings &#xff1a;编写config文件&#xff0c;记录上次打开图片的位置&#xff0c;下次打开图片会从上次的位置查找图片。 QPixmap&#xff1a;用于图片的缩放&#xff0c;防止图片过小&#xff0…...

LLM大模型相关问题汇总---包括问题与答案

一、基础篇 1. 目前主流的开源模型体系有哪些&#xff1f; - Transformer体系&#xff1a;由Google提出的Transformer模型及其变体&#xff0c;如BERT、GPT等。 - PyTorch Lightning&#xff1a;一个基于PyTorch的轻量级深度学习框架&#xff0c;用于快速原型设计和实验…...

自动化测试定位不到元素怎么办?

1.动态id定位不到元素 分析原因&#xff1a;每次打开页面&#xff0c;ID都会变化。用ID去找元素&#xff0c;每次刷新页面ID都会发生变化。 解决方案&#xff1a;推荐使用xpath的相对路径方法或者cssSelector查找到该元素。 2.iframe原因定位不到元素 分析原因&#xff1a;…...

1 scala集合-数组

1 定长数组 定长数组&#xff0c;是指数组长度不可变。定义定长数组的方法有如下两种&#xff1a; 方法1&#xff1a; var/val variable_name new Array[元素类型](数组长度) // 通过制定长度定义例如&#xff0c;定义一个长度为20的Int 类型数组。 scala> val a new …...

双场板功率GaN HEMT电容模型以精确模拟开关行为

标题&#xff1a;Capacitance Modeling in Dual Field-Plate Power GaN HEMT for Accurate Switching Behavior&#xff08;TED.16年&#xff09; 摘要 本文提出了一种基于表面电位的紧凑模型&#xff0c;用于模拟具有栅极和源极场板&#xff08;FP&#xff09;结构的AlGaN/G…...

OpenCV Mat实例详解 四

OpenCV Mat实例详解三中详细介绍来了OpenCV Mat类的公有静态成员函数&#xff0c;下面介绍OpenCV Mat类的其他常用成员函数。 OpenCV Mat类常用成员函数 Mat & adjustROI (int dtop, int dbottom, int dleft, int dright)&#xff1b; dtop ROI 上边界移动值&#xff0c;如…...

Fluke ADPT 连接器新增对福禄克万用 Fluke 106 的支持

所需设备&#xff1a; 1、Fluke ADPT连接器&#xff1b; 2、Fluke 106&#xff1b; Fluke 106 拆机图&#xff1a; 显示界面如下图&#xff1a; 并且可以将波形导出到EXCEL: 福禄克万用表需要自己动手改造&#xff01;&#xff01;&#xff01;...

算法-3-基本的数据结构

单双链表 1.单链表双链表如何反转 import java.util.ArrayList; import java.util.List;public class Code01_ReverseList {public static class Node {public int value;public Node next;public Node(int data) {value data;}}public static class DoubleNode {public int…...

探秘Java反射:灵活编程的利器

前言 大家好&#xff0c;我是chowley&#xff0c;不知道大家在学习Java的过程中有没有听过反射的概念&#xff0c;今天我来总结一下我心中的Java反射。 在Java编程中&#xff0c;反射是一种强大的工具&#xff0c;它允许程序在运行时检查和操作类、方法、属性等&#xff0c;而…...

记录 | ubuntu pyqt5 pycharm配置

Ubuntu16.04pycharmpyqt5安装与配置_ubuntu pycharm pyqt5-CSDN博客pycharm激活码 6ZUMD7WWWU-eyJsaWNlbnNlSWQiOiI2WlVNRDdXV1dVIiwibGljZW5zZWVOYW1lIjoiSmV0cyBHcm91cCIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiIiLCJjaGVja0NvbmN…...

ESP32学习(1)——环境搭建

使用的ESP32板子如下图所示 它可以用Arduino 软件&#xff0c;基于C语言开发。但是&#xff0c;在这里&#xff0c;我是用Thonny软件&#xff0c;基于micro_python对其进行开发。 1.安装Thonny Thonny的软件安装包&#xff0c;可以去它官网上下载。Thonny, Python IDE for begi…...

Attention Is All Your Need论文笔记

论文解决了什么问题&#xff1f; 提出了一个新的简单网络架构——transformer&#xff0c;仅仅是基于注意力机制&#xff0c;完全免去递推和卷积&#xff0c;使得神经网络训练地速度极大地提高。 We propose a new simple network architecture, the Transformer, based sole…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...