【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类。

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

📝文章结语:

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLO目标检测——森林火灾烟雾检测数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;森林火灾监控与预警标注说明&#xff1a;使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(xml)、coco(json)和yolo(txt)三种格式标签&#xff0c;分别存放在不同文件夹下&#xff0c;可以直接用于YOLO系列的目标检测。其他&#x…

3D-Genome | Hi-C互作矩阵归一化指南

Hi-C 是一种基于测序的方法&#xff0c;用于分析全基因组染色质互作。它已广泛应用于研究各种生物学问题&#xff0c;如基因调控、染色质结构、基因组组装等。Hi-C 实验涉及一系列生物化学反应&#xff0c;可能会在输出中引入噪声。随后的数据分析也会产生影响最终输出噪声&…

PandasAI—让AI做数据分析

安装 pip install pandasai !pip install --upgrade pandas pandasai 导入依赖项 import pandas as pdfrom pandasai import PandasAIfrom pandasai.llm.openai import OpenAI使用pandas创建一个数据框 df pd.DataFrame({"country": ["United States",…

VisionPro 判断圆是不是无限接近圆或存在缺陷

项目上可能需要判断圆是否是无限接近圆或者判断圆边缘是否存在缺陷等。 第一种方法&#xff1a;找圆工具和点到点的距离计算圆边缘上的点到圆心距离的最大值和最小值的差值。 #region namespace imports using System; using System.Collections; using System.Drawing; usin…

Batch Nomalization 迁移学习

Batch Nomalization 1.Batch Nomalization原理 图像预处理过程中通常会对图像进行标准化处理&#xff0c;这样能够加速网络的收敛。就是按照channel去求均值和方差&#xff0c;然后原数据减均值除标准差&#xff0c;使我们的feature map满足均值为0&#xff0c;方差为1的分布…

AI助力剧本创作:如何5分钟内构思出热门短剧大纲

人工智能重塑短剧行业&#xff1a;从剧本创作到市场推广 在当今短剧行业的飞速发展中&#xff0c;剧本创作的质量及其更新的速度已然成为短剧能否转化为热门作品的关键性因素。然而&#xff0c;随着短剧创作成本的日益攀升&#xff0c;一个卓越的剧本无论在创作时间上还是在构思…

基于SpringBoot+MYSQL的大学生租房平台

目录 1、 前言介绍 2、主要技术 3、系统流程 3.1、操作流程 3.2、登录流程 3.3、删除信息流程 3.4、添加信息流程 4、功能需求 5、系统设计 5.1、功能结构设计 5.1、数据库概念设计 6、运行截图(部分) 6.1、管理员功能实现 6.1.1、房东管理 6.1.2、信息审批管理 …

物联网在智慧城市建设中的关键作用:连接、感知、智能响应

一、引言 随着信息技术的飞速发展&#xff0c;物联网&#xff08;IoT&#xff09;技术已经渗透到我们生活的方方面面&#xff0c;特别是在智慧城市建设中发挥着至关重要的作用。智慧城市是指通过运用先进的信息和通信技术&#xff0c;实现城市基础设施、公共服务、交通管理、环…

断开服务器仍后台运行程序

1.可以使用nohup命令&#xff1a; nohup python xx.py 2>1& 不要忘记 2>1& 之后会返回一个进程号&#xff08;记不住也没关系&#xff0c;可以看3&#xff09;&#xff0c;此时程序就在后台运行了&#xff0c;与服务器断开连接也能正常运行 2.在终端实时打印…

ai绘画是怎么画的?ai绘画算法揭秘 - AI绘画每日一帖

“ AI 绘画通过CLIP技术建立「文字潜在空间」到「图片潜在空间」的对应关系&#xff0c;并通过 Diffusion 技术从一张噪点图得到一张有信息的高清图。 在 一文讲透ai作画原理技术 一文中&#xff0c;我们介绍了ai绘画的基本原理&#xff0c;这背后更详细的ai绘画算法是什么&…

Visual Studio如何进行类文件的管理(类文件的分离)

大家好&#xff1a; 衷心希望各位点赞。 您的问题请留在评论区&#xff0c;我会及时回答。 一、问题背景 实际开发中&#xff0c;类的声明放在头文件中&#xff0c;给程序员看类的成员和方法。比如&#xff1a;Dog.h&#xff08;类的声明文件&#xff09; 类的成员函数的具体…

stable diffusion 原理是什么?

“ 这篇文章主要介绍了Stable Diffusion&#xff0c;这是一种用于AI绘画的算法&#xff0c;它是由CompVis和Runway团队在2021年12月提出的“潜在扩散模型”&#xff08;LDM/Latent Diffusion Model&#xff09;的变体&#xff0c;基于2015年提出的扩散模型&#xff08;DM/Diffu…

场景问题: VisualVM工具Profiler JDBC不是真实执行的SQL

1. 问题 诡异的问题表象&#xff1a; 前端反馈分页接口的Total字段一直为0 使用Visualvm中的 Profiler 注入到应用后&#xff0c;查看JDBC监控得到了分页接口执行的SQL&#xff0c;复制出来执行是55. 此时还没有注意到 IN 的范围中有一个特别的值 NULL &#x1f928; 2. 排查…

2834. 找出美丽数组的最小和

文章目录 [2834. 找出美丽数组的最小和](https://leetcode.cn/problems/find-the-minimum-possible-sum-of-a-beautiful-array/)思路&#xff1a;代码&#xff1a; 2834. 找出美丽数组的最小和 思路&#xff1a; 1.n 是数组的长度。k 是题目中的target。m 的值是通过取k / 2和…

提取pdf图档中的物料编码

一、摘要 图1 图档示例 本篇代码目的是从指定文件夹下的PDF文件中提取物料编码等相关信息&#xff0c;并将这些信息存储在列表中输出。这段代码主要实现了以下功能&#xff1a; 定义一个file_name函数&#xff0c;用于获取指定文件夹下所有文件的完整路径。通过遍历文件夹和子文…

UOS 与 Ubuntu 命令行打开安装包界面,双击打开界面调用安装包界面展示

UOS 使用deepin-deb-installer安装程序 deepin-deb-installer xxxxxxx.deb & Ubuntu snap-store --local-filename /home/seven/wps-office_1xxxxxxx.deb &

Android14音频进阶:AudioTrack如何拿到AudioFlinger创建的匿名共享内存(六十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

聚观早报 | 腾讯QQ测试AI对话功能;哪吒L官宣4月交付

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 3月8日消息 腾讯QQ测试AI对话功能 哪吒L官宣4月交付 中国对瑞士等6国试行免签 Redmi K70至尊版细节曝光 Meta正…

如何阅读“计算机界三大神书”之一 ——《计算机程序的构造和解释》SICP

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

git分布式管理-头歌实验冲突处理、忽略文件

一、解决冲突 任务描述 在团队协作开发过程中&#xff0c;可能你和团队中的其他成员&#xff0c;都修改了某个文件的某一部分内容&#xff0c;且其他成员已将该修改推送到了远程仓库。这样当你需要合并他的代码的时候&#xff0c;可能就会在内容上出现冲突&#xff0c;这个时候…