【C++干货基地】六大默认成员函数: This指针 | 构造函数 | 析构函数


在这里插入图片描述

🎬 鸽芷咕:个人主页

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

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

引入

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

⛳️ 推荐

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

文章目录

  • 引入
  • ⛳️ 推荐
  • 一、this指针的概念
    • 1.1 this 指针的引入
    • 1.2 this 指针的特性
      • this 指针存在哪里
      • this指针可以为空吗?
  • 二、六个默认成员函数
  • 三、构造函数
    • 3.1 构造函数的概念
    • 3.2 构造函数的特性
      • 无参构造函数
      • 无参的默认构造函数
  • 四、析构函数
    • 4.1 析构函数函数的概念
    • 4.2 析构函数的特性
  • 📝文章结语:

一、this指针的概念

1.1 this 指针的引入

来讲 this 之前我们先来看一下下面这段代码:

  • 这里 printf 函数我们并没有传递参数那么他如何知道我们打印的是那个对象对的呢?
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;class Data
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void print(){cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;
};int main()
{Data d1,d2;d1.Init(2023, 2, 27);d2.Init(2023, 4, 07);d1.print();return 0;
}

这里我们去调用 d1.print(); 但是 print 函数并没有参数是如何知道要打印 ?

其实在C++这里虽然我们没有给print 函数参数,但实际上是有一个默认的this 指针来自动调用的,实际的代码可能是下面这样但是编译器给自动化了大大简化了用户操作。

在这里插入图片描述

C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

1.2 this 指针的特性

  1. this指针的类型:类类型 const,即成员函数中,不能给this指针赋值。*
  2. 只能在“成员函数”的内部使用
  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

this 指针存在哪里

this 前面我们说了 其实是我们成员函数的形参,所以 this 指针其实是存放在 栈区的。(有些编译比如vs可能会用寄存器存储)

this指针可以为空吗?

这个问题我们就来看下下面这俩个练习题了:

🍸 代码演示:

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();return 0;
}

这个小程序相信大家都看得出来是选 C 虽然我们的 p 是一个空指针但是调用函数的时候并不会传递this 指针,或者使用空指针所以程序正常运行

🍸 代码演示:

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void PrintA(){cout << _a << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->PrintA();return 0;
}

而这个程序就不可以了,我们对空指针进行解引用一定对引发程序崩溃

  • 因为我们使用了成员变量 _a ,但成员变量的地址又是一个空地址

在这里插入图片描述

二、六个默认成员函数

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

在这里插入图片描述

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

同时这六个默认成员函数也是我们面向对象的核心,下面我们就来先介绍一下构造函数和析构函数

三、构造函数

3.1 构造函数的概念

构造函数咋一听名字各位是不是觉得他是用来创建函数的,其实大家是被名字误导了。构造函数的实际作用就是 和 Init 函数一样,用来初始化我们的对象:

  • 以往我们初始化对象都需要自己去手动调用,非常麻烦
  • 单是构造函数这种默认成员函数就不需要了,自动调用帮我们初始化化
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Init(2022, 7, 5);d1.Print();Date d2;d2.Init(2022, 7, 6);d2.Print();return 0;
}

这里我们每次调用日期类都要给它,去初始化太麻烦了,但是使用构造函数来进行初始化就方便很多

🍸 代码演示:

class Date
{
public:Date(int year = 2023, int month = 2, int day = 29){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Print();Date d2(2022, 7, 6);d2.Print();return 0;
}

3.2 构造函数的特性

构造函数是一个默认成员函数,也是一个非常特殊的成员函数。可以帮助我们自动初始化对象,而且自动调用它有以下一个特性

  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();
}

无参的默认构造函数

如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦
用户显式定义编译器将不再生成。

但是这个构造函数对,内置类型不处理,对自定义类型调用它的默认函数

在这里插入图片描述
比如说这里我们就没有去显示创建构造函数,但是自动创建了一个默认构造函数,默认构造函数

  • 对自定义类型调用他的构造函数
  • 对内置类型不做处理

这里很多人就觉得为什么对内置类型不处理,自动处理了不是更好吗?可能是祖师爷在编写的打了个盹给搞忘了(哈哈哈开个玩笑)

  • 🔥 所以在C++11的时候对这里打了补丁,即:内置类型成员变量在类中声明时可以给默认值。

🍸 代码演示:

class Date
{
public:void print(){cout << _year  << _month  << _day << endl;}private:int _year = 2023;int _month = 2;int _day = 17;
};int main()
{Date a1;return 0;
}

📑代码结果:
在这里插入图片描述

  • 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。

注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数

四、析构函数

4.1 析构函数函数的概念

构造函数是用来自动初始化对象的,那么自动清理对象是用那个呢?没错这就是析构函数该干的工作了,析构函数主要负责清理空间和我们以前数据结构中的 destroy 销毁空间的作用是一样的!

4.2 析构函数的特性

析构函数是特殊的成员函数,其特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

🍸 代码演示:

class Date
{
public:void print(){cout << _year  << _month  << _day << endl;}~Date(){cout << "time~" << endl;}
private:int _year = 2023;int _month = 2;int _day = 23;
};int main()
{Date a1;return 0;
}

在这里插入图片描述

这里我们就可以看到了,我们不取调用析构函数,但是在程序结束的时候自动调用

  • 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器
    生成的默认析构函数,对自定类型成员调用它的析构函数。

这里析构函数和构造函数是一模一样的,对自定义类型才会去默认调用它的析构函数

class Time
{
public:~Time(){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 d;return 0;
}
  • 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如
    Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。

因为析构函数一般是用来释放我们申请的空间,而内置类型在程序结束会自动释放空间所以没有申请资源可以不写析构函数

📝文章结语:

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

在这里插入图片描述

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

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

相关文章

平台工程指南:从架构构建到职责分工

平台工程只是 DevOps 专业化的另一个术语&#xff0c;还是另有所指&#xff1f;事实可能介于两者之间。DevOps 及其相关的 DevXOps 有着浓厚的文化色彩&#xff0c;以各个团队为中心。不幸的是&#xff0c;在许多地方&#xff0c;DevOps 引发了新的问题&#xff0c;如工具激增和…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑净负荷均衡的分布式光伏集群电压调控策略研究》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

智引未来:2024年科技革新引领工业界变革与机遇

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

MS5188N——16bit、8 通道、500kSPS、 SAR 型 ADC

产品简述 MS5188N 是 8 通道、 16bit 、电荷再分配逐次逼近型模数 转换器&#xff0c;采用单电源供电。 MS5188N 拥有多通道、低功耗数据采集系统所需的所有 组成部分&#xff0c;包括&#xff1a;无失码的真 16 位 SAR ADC &#xff1b;用于将输入配 置为单端输入…

算法优化 —— 注意力机制篇

文章目录 前言一、EMA 高效多尺度注意力机制(ICASSP2023)二、BiFormer: 基于动态稀疏注意力构建高效金字塔网络架构(2023CVPR)前言 提示:这里可以添加本文要记录的大概内容: 一、EMA 高效多尺度注意力机制(ICASSP2023) 原论文链接 代码如下: class EMA(nn.Module

【观点】区块链的未来:分布式商业;企业的未来:分布式商业生态战略

本文内容摘自思二勋所著的《分布式商业生态战略》一书。 近两年&#xff0c;商业经济环境的不确定性越来越明显&#xff0c;市场经济受到疫情、技术、政策等多方因素影响越来越难以预测&#xff0c;黑天鹅事件时有发生。在国内外经济方面&#xff0c;国际的地缘政治对商业经济…

消息队列-Kafka-消费方如何分区与分区重平衡

消费分区 资料来源于网络 消费者订阅的入口&#xff1a;KafkaConsumer#subscribe 消费者消费的入口&#xff1a;KafkaConsumer#poll 处理流程&#xff1a; 对元数据重平衡处理&#xff1a;KafkaConsumer#updateAssignmentMetadataIfNeeded 协调器的拉取处理&#xff1a;onsum…

LVGL在VScode中安装模拟器运行配置笔记教程

1、LVGL模拟器工程搭建 LVGL(Light and Versatile Graphics Library,轻巧而多功能的图形库)是一个免费的开放源代码图形库,它提供创建具有易于使用的图形元素,精美的视觉效果和低内存占用的嵌入式GUI所需的一切。本文主要讲述如何实现在VScode中实现LVGL模拟器环境的搭建运行。…

【RT-DETR有效改进】全新的SOATA轻量化下采样操作ADown(轻量又涨点,附手撕结构图)

一、本文介绍 本文给大家带来的改进机制是利用2024/02/21号最新发布的YOLOv9其中提出的ADown模块来改进我们的Conv模块,其中YOLOv9针对于这个模块并没有介绍,只是在其项目文件中用到了,我将其整理出来用于我们的RT-DETR的项目,经过实验我发现该卷积模块(作为下采样模块)…

Mybatis从入门到CRUD到分页到日志到Lombok到动态SQL再到缓存

Mybatis 入门 1.导入maven依赖 <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>x.x.x</version> </dependency>2.配置核心文件 <?xml version"1.0" encoding"U…

【金三银四的季节看下Java ORM的走向和性能对比】总结

写在最后 经过将近一周时间的框架收集、学习、实验、编码、测试市面上常见的ORM框架&#xff0c;过程中拜读了很多作者的博文、样例&#xff0c;学习很多收获很多。 重新梳理下整理的框架&#xff1a;mybatis-plus、lazy、sqltoy、mybatis-flex、easy-query、mybatis-mp、jpa、…

HTML静态网页成品作业(HTML+CSS)——电影网首页网页设计制作(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…