C++(六个默认成员函数)

目录

  • 六个默认成员函数
    • 构造函数
    • 析构函数
    • 拷贝构造函数
  • 总结

六个默认成员函数

默认成员函数的概念:如果用户不显式写,编译器会自动生成的函数,就是默认成员函数

构造函数

构造函数是六个默认成员函数之一,构造函数的功能类似于init,起了初始化的功能,构造函数的名字和类的名字相同,构造函数可以无参有参有参全缺省,构造函数在创建对象时,编译器会自动调用。

特性:

  1. 函数名和类名相同
  2. 无返回值
  3. 类的实例化时会自动调用
  4. 构造函数可以重载
class Date{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};void TestDate(){Date d1; // 调用无参构造函数Date d2(2015, 1, 1); // 调用带参的构造函数// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)Date d3();}
  1. 如果类中没有显式写构造函数,则编译器会自动生成一个无参的构造函数,如果显式写了构造函数,编译器则不会自动生成构造函数。

注意:在C++中,定义了构造函数会自动调用,但是在实际中vs是不会调用构造函数的,所以C++11打了一个补丁就是可以在声明类的成员的时候可以增加一个缺省值,在编译的过程中,就会根据成员变量的缺省值来对对象进行初始化。

class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}

上面的代码在对类中的成员声明时就会根据参数的缺省值进行初始化,这是在没有显式写构造函数的时候。

注意:全缺省的构造函数、无参的构造函数、和编译器默认生成的构造函数都可以作为编译器默认的构造函数

并且默认的构造函数只能有一个,意思就是这三个构造函数只能有一个,如果前两个同时存在,虽然构成重载,但是调用时编译器会产生歧义。

析构函数

析构函数的工作类似于destroy,但是对于内置类型一般不需要调用析构函数,一般需要用析构函数的是malloc出空间,还有new出来的空间。

特征:

  1. 析构函数和构造函数类似函数名和构造函数稍微有点区别,只需要在类名前面加上一个~,就是析构函数。
  2. 无参无返回值
  3. 第二条说无参,也就造成了析构函数不能进行函数重载
  4. 在对象的生命周期结束时,C++编译器会自动调用析构函数

让我们用下面的一个类来检测一下,编译器是否自动调用了析构函数

#include<iostream>
#include<cstdlib>
using namespace std;typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}// 其他方法...~Stack(){cout << "~Stack";if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:DataType* _array;int _capacity;int _size;
};
void TestStack()
{Stack s;s.Push(1);s.Push(2);
}int main()
{Stack st;return 0;
}

可以看到在我们显式实现的析构函数中,我在析构函数中加了一个cout,如果编译器自动调用了,则会在屏幕上打印一个~Stack,反之则不会打印。
从下图运行结果看,可以看出,编译器会自动调用析构函数。
在这里插入图片描述
6. 如果类中没有申请资源,析构函数可以不写,直接使用编译器生成的析构函数,比如:Date类,如Stack类的就需要自己完善一个析构函数。

拷贝构造函数

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

特征:

  1. 拷贝构造函数是构造函数的一种重载形式。
  2. 拷贝构造函数的参数只有一个就是传递的类的引用,如果进行传值调用的话就会产生无穷递归,编译器会报错。

对于第二点,为什么会产生无穷递归呢?

首先需要了解的一点是,编译器在对自定义类型进行传值传参的时候,会直接调用拷贝构造函数,所以当我有一个func函数的时候,需要传递一个自定义类型,则在传递之前,需要先调用拷贝构造函数,然后再去调用func函数。

了解上面之后,接下来我们就来讨论为什么传值传参会产生无穷递归,首先我们传值的话会调用拷贝构造函数,调用拷贝构造函数的话,因为调用拷贝构造函数的参数也是一个自定义类型,所以又会继续调用拷贝构造函数,接着就会一直进行递归调用,最后就会崩溃,接下来用图来展示::
在这里插入图片描述

  1. 如果没有显式定义拷贝构造函数则编译器会自动生成一个默认的拷贝构造函数,并且在调用的时候会成功,但是需要注意的是这里编译器生成的拷贝构造函数是浅拷贝,而不是深拷贝

所谓的浅拷贝就是值拷贝,只拷贝值,深拷贝就是比如我原来有一块malloc出来的空间,深拷贝会自动申请一块和以前那块一样的空间,然后将值拷贝进去,而浅拷贝,则会和以前malloc出来的空间共用一个空间,这样会导致一个问题,我们拿栈来举例,如果我们用编译器自动生成的浅拷贝的话,当我们拷贝完成的时候,如果以前的空间再次进行push的话以前的size会++,但是新的size则不会++,还有一个严重的问题就是浅拷贝的话,析构函数会调用两次,对同一块空间进行两次释放,会产生很大问题。

在这里插入图片描述

如上图所示

5. 拷贝构造函数典型调用场景:
–使用已存在对象创建新对象
–函数参数类型为类类型对象
–函数返回值类型为类类型对象

总结

默认构造函数(Default Constructor):如果我们没有定义任何构造函数,编译器将会生成一个默认构造函数。默认构造函数不接受任何参数,并且执行成员变量的默认初始化。在很多情况下,这可能是合适的,但如果类的成员需要特定的初始化值,可能需要显式定义构造函数。

析构函数(Destructor):如果我们没有提供析构函数,编译器会生成一个默认的析构函数。默认析构函数会释放对象所占用的内存,如果对象包含有指针成员,可能不会正确地释放内存或执行其他必要的清理工作。如果类需要在对象销毁时执行特定操作,比如释放资源或者清理其他状态,就需要显式定义析构函数。

拷贝构造函数(Copy Constructor):如果我们没有定义拷贝构造函数,编译器会生成一个默认的拷贝构造函数。默认拷贝构造函数会执行浅拷贝(shallow copy),即对于指针成员只复制指针而不复制指针所指向的对象。这可能导致浅拷贝问题,即多个对象共享同一块内存。如果类含有指针成员,或者需要进行深拷贝或其他特殊处理,就需要显式定义拷贝构造函数。

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

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

相关文章

C#面:什么链式委托

链式委托是指将多个委托实例连接在一起&#xff0c;形成一个委托链&#xff0c;使得多个方法可以按照一定的顺序依次被调用。 在C#中&#xff0c;可以使用""运算符来连接多个委托实例&#xff0c;形成一个新的委托实例。 当调用链式委托时&#xff0c;每个委托实例都…

懒人必备!4个PS抠图技巧,让你轻松处理复杂背景!

今天带给大家的又是一个绝对重要的知识&#xff0c;那就是“抠图”&#xff01; 在我们的设计中&#xff0c;抠图可以说是最常见的运用啦&#xff0c;简单的PS抠图我们都会&#xff0c;但是最令我们头痛的人物或者动物的毛发的抠图了&#xff0c;很多人都抠不好&#xff0c;我…

合并单元格的excel文件转换成json数据格式

github地址: https://github.com/CodeWang-Ay/DataProcess 类型1 需求1: 类似于数据格式: https://blog.csdn.net/qq_44072222/article/details/120884158 目标json格式 {"位置": 1, "名称": "nba球员", "国家": "美国"…

华为机试题

目录 第一章、HJ1计算字符串最后一个单词的长度&#xff0c;单词以空格隔开。1.1&#xff09;描述1.2&#xff09;解题第二章、算法题HJ2 计算某字符出现次数1.1&#xff09;题目描述1.2&#xff09;解题思路与答案第三章、算法题HJ3 明明的随机数1.1&#xff09;题目描述1.2&a…

eBPF专题一 | 手把手教你用eBPF诊断MySQL(含源码)

DBdoctor 是一款数据库内核级性能诊断工具&#xff0c;利用eBPF技术深入数据库内核&#xff0c;致力于解决数据库的一切性能问题。 被称之为“革命性”内核技术的eBPF一直以来都备受关注&#xff0c;而DBdoctor作为一款数据库性能诊断工具&#xff0c;首次将eBPF技术深入应用…

centos 安装 stable-diffusion 详细流程

一、准备环境 安装git 新版 先安装git 工具来更新git源码 &#xff0c; 载下源码后卸载git 版本(centos 默认1.8版本&#xff0c;说是安装会引起失败) 安装git 命令&#xff0c;可使用 git --version查看版本 sudo yum install git -y 卸载git命令 sudo yum remove git 正式…

golang 中 sync包

WaitGroup WaitGroup 的用途&#xff1a;它能够一直等到所有的 goroutine 执行完成&#xff0c;并且阻塞主线程的执行&#xff0c;直到所有的 goroutine 执行完成。 WaitGroup 总共有三个方法&#xff1a;Add(delta int), Done(), Wait()。简单的说一下这三个方法的作用。 Add&…

FPGA实现Canny算法(Verilog)

在边缘检测算法里面Sobel是比较简单的一个算法&#xff0c;但是其检测出来的边缘往往是比较粗的&#xff0c;效果不是很好&#xff0c;因为我们最理想的边缘肯定就是一个宽度为1的细线。 Canny算法在此基础上进行了改进&#xff0c;通过使用边缘的梯度信息进行非最大值抑制(NM…

PCL 点到圆柱的距离(3D)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里的思路也很简单,我们只需要将点转换到圆柱坐标系下,在该系统中,点(0,0,0)为圆柱轴原点,(0,0,1)为圆柱轴方向,那么此时计算点到圆柱的距离就简单很多了,我们可以利用正射投影快速的获得距离结果。 二、实现…

【随笔】Git 高级篇 -- 最近标签距离查询 git describe(二十一)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

【计算机毕业设计】企业仓储管理系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

5.消息队列

消息队列 ​ 消息队列是一种常用的线程间通讯方式&#xff0c;用来传输数据。使用消息队列传输数据时有两种方法&#xff1a;拷贝&#xff1a;把数据、把变量的值复制进消息队列里&#xff1b;引用&#xff1a;把数据、把变量的地址复制进消息队列里。rtt使用拷贝值的方法。 …

python-pytorch实现CBOW 0.5.000

python-pytorch实现CBOW 0.5.000 数据加载、切词准备训练数据准备模型和参数训练保存模型加载模型简单预测获取词向量降维显示图使用词向量计算相似度参考 数据加载、切词 按照链接https://blog.csdn.net/m0_60688978/article/details/137538274操作后&#xff0c;可以获得的数…

由近期 RAGFlow 的火爆看 RAG 的现状与未来

4 月 1 日&#xff0c;InfiniFlow &#xff08;英飞流&#xff09;的端到端 RAG 解决方案 RAGFlow 正式开源&#xff0c;首日即获得了 github 千星&#xff0c;目前已接近 3000 star。在这之前&#xff0c;InfiniFlow 还开源了专门用于 RAG 场景的 AI 原生数据库 Infinity&…

用 ElementPlus 的日历组件 Calendar 自定义渲染

文章目录 需求分析1. 英文改为中文2. 修改样式3. 自定义头部4. 增删改功能接入需求 使用 ElementPlus中的 Calendar 组件完成自定义渲染 分析 1. 英文改为中文 转为中文的方式:用 ElementPlus的日历组件如何改为中文 2. 修改样式 附源码<template><el-calendar&…

[工程经验] 模块设计规范

模块设计规范 文章目录 模块设计规范1.需求2.概念与逻辑图3.主要的数据结构图4.算法5.接口定义 1.需求 根据需求文档&#xff0c;摘录模块的对应部分&#xff0c;细化到可指导开发的程度&#xff0c;并根据实现的需要进行拓展&#xff0c;落地为一份设计文档。 2.概念与逻辑图…

linux查看硬盘空间使用情况

df &#xff08;1&#xff09;查看磁盘空间的占用情况 -h是给大小带上单位 df -h 总空间不一定等于已用未用&#xff0c;系统可能留出来一点空间另做他用 &#xff08;2&#xff09;查看INode的使用情况 df -idu du命令比df命令复杂一点&#xff0c;是查看文件和目录占用的…

【排序算法】七、快速排序补充:三指针+随机数法

「前言」文章内容是对快速排序算法的补充&#xff0c;之前的算法流程细节多难处理&#xff0c;这里补充三指针随机数法&#xff08;递归&#xff09;&#xff0c;这个容易理解&#xff0c;在时间复杂度上也更优秀 「归属专栏」排序算法 「主页链接」个人主页 「笔者」枫叶先生(…

Docker-compose部署Alertmanager+Dingtalk+Prometheus+Grafana实现钉钉报警

部署监控 version: 3.7services: #dingtalkdingtalk:image: timonwong/prometheus-webhook-dingtalk:latestcontainer_name: dingtalkrestart: alwayscommand:- --config.file/etc/prometheus-webhook-dingtalk/config.ymlvolumes:- /data/monitor/dingtalk/config.yml:/etc/p…

部署GlusterFS群集

目录 一、部署GlusterFS群集 1. 服务器节点分配 2. 服务器环境&#xff08;所有node节点上操作&#xff09; 2.1 关闭防火墙 2.2 磁盘分区&#xff0c;并挂载 2.3 修改主机名&#xff0c;配置/etc/hosts文件 3. 安装、启动GlusterFS&#xff08;所有node节点上操作&…