【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.rhkb.cn/news/271678.html

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

相关文章

听 GPT 讲 client-go 源代码 (24)

分享更多精彩内容&#xff0c;欢迎关注&#xff01; File: client-go/applyconfigurations/batch/v1/jobstatus.go 在client-go的applyconfigurations/batch/v1/jobstatus.go文件中&#xff0c;定义了与Job的状态相关的配置和操作。 文件中定义了以下几个结构体&#xff1a; Jo…

Kube-Prometheus 监控Istio

推荐 Istio 多集群监控使用 Prometheus&#xff0c;其主要原因是基于 Prometheus 的分层联邦&#xff08;Hierarchical Federation&#xff09;。 通过 Istio 部署到每个集群中的 Prometheus 实例作为初始收集器&#xff0c;然后将数据聚合到网格层次的 Prometheus 实例上。 网…

Kruscal建树+倍增LCA,蓝桥2023省赛,网络稳定性

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 2.网络稳定性 - 蓝桥云课 (lanqiao.cn) 二、解题报告 1、思路分析 考虑到…

自动驾驶预测与决策规划(nuplan数据集)

欢迎大家关注我的B站&#xff1a; 偷吃薯片的Zheng同学的个人空间-偷吃薯片的Zheng同学个人主页-哔哩哔哩视频 (bilibili.com) 目录 1.概述 2 数据采集 3.开环与闭环仿真 4.数据注释 5.场景 6.规划框架 6.1Train 6.2Simulation 6.3Metric 6.4Visualization 7.下载…

【2024.03.05】定时执行专家 V7.1 发布 - TimingExecutor V7.1 Release

目录 ▉ 软件介绍 ▉ 新版本 V7.1 下载地址 ▉ V7.1 新功能 ▼2024-03-03 V7.1 - 更新日志 ▉ V7.0 新UI设计 ▉ 软件介绍 《定时执行专家》是一款制作精良、功能强大、毫秒精度、专业级的定时任务执行软件。软件具有 25 种【任务类型】、12 种【触发器】触发方式&#x…

基于51单片机风速仪风速测量台风预警数码管显示

基于51单片机风速仪风速测量报警数码管显示 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真4. 程序代码5. 设计报告&#x1f517;6. 下载链接资料下载链接&#xff1a; 基于51单片机风速仪风速测量报警数码管显示( proteus仿真程序设计报告讲解视频&#xff09; 仿真图…

CRMCHAT修复获取客户ip信息,地区信息

CRMCHAT修复获取客户ip信息&#xff0c;地区信息-TP源码网原因&#xff1a; 因pv.sohu.com/cityjson?ieutf-8接口已无法正确获取ip信息&#xff0c;导致后台站点统计无法正确获取用户ip信息&#xff0c;无法获取地区信息 修改 注释掉无用接口地址 修复ip信息 也可以使用&…

【Lazy ORM】 小工具 acw 本地客户端 你负责点击页面,他负责输出代码

介绍 wu-smart-acw-client 简称acw-client&#xff0c;是一个基于Lazy ORM定制的客户端代码生成小工具 Lazy ORM 小工具 acw 本地客户端 你负责点击页面&#xff0c;他负责输出代码安装 <dependency><groupId>top.wu2020</groupId><artifactId>wu-sma…

即插即用篇 | YOLOv8 引入 ParNetAttention 注意力机制 | 《NON-DEEP NETWORKS》

论文名称:《NON-DEEP NETWORKS》 论文地址:https://arxiv.org/pdf/2110.07641.pdf 代码地址:https://github.com/imankgoyal/NonDeepNetworks 文章目录 1 原理2 源代码3 添加方式4 模型 yaml 文件template-backbone.yamltemplate-small.yamltemplate-large.yaml

2024蓝桥杯每日一题(前缀和)

一、第一题&#xff1a;壁画 解题思路&#xff1a;前缀和贪心枚举 仔细思考可以发现B值最大的情况是一段连续的长度为n/2上取整的序列的累加和 【Python程序代码】 import math T int(input()) for _ in range(1,1T):n int(input())s input()l math.ceil(len(s)/…

图文并茂的讲清楚Linux零拷贝技术

今天我们来聊一聊Linux零拷贝技术&#xff0c;今天我们以一个比较有代表性的技术sendfile系统调用为切入点&#xff0c;详细介绍一下零拷贝技术的原理。 1.零拷贝技术简介 Linux零拷贝技术是一种优化数据传输的技术&#xff0c;它可以减少数据在内核态和用户态之间的拷贝次数&…

Linux报错排查-刚安装好的ubuntu系统无法ssh连接

Linux运维工具-ywtool 目录 一.问题描述二.问题解决2.1 先给ubuntu系统配置阿里云源2.2 安装openssh-server软件2.3 在尝试ssh连接,可以连接成功了 三.其他命令 一.问题描述 系统:ubuntu-18.04-desktop-amd64 系统安装完后,想要通过xshell软件连接系统,发现能Ping通系统的IP,但…

【探索Linux】—— 强大的命令行工具 P.26(网络编程套接字基本概念—— socket编程接口 | socket编程接口相关函数详细介绍 )

阅读导航 引言一、socket 常见API表二、函数详细介绍01. socket()02. bind()03. listen()04. accept()05. connect()06. send()07. recv()08. close()09. select()10. getaddrinfo()11. sendto()12. recvfrom()13. setsockopt()14. getsockopt()15. shutdown()16. inet_pton()1…

昇腾芯片解析:华为自主研发的人工智能处理器全面分析

在当今科技发展的浪潮中&#xff0c;昇腾芯片作为一种新兴的处理器&#xff0c;正引起广泛的关注和讨论。升腾芯片究竟是由哪家公司生产的&#xff1f;这个问题一直困扰着许多人。下面小编将全面介绍、分析升腾芯片的生产商及各类参数、应用&#xff0c;以便读者对其有更全面的…

centos7 python3.12.1 报错 No module named _ssl

https://blog.csdn.net/Amio_/article/details/126716818 安装python cd /usr/local/src wget https://www.python.org/ftp/python/3.12.1/Python-3.12.1.tgz tar -zxvf Python-3.12.1.tgz cd Python-3.12.1/ ./configure -C --enable-shared --with-openssl/usr/local/opens…

C++:Stack和Queue的模拟实现

创作不易&#xff0c;感谢三连&#xff01; 一、容器适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结)&#xff0c;该种模式是将一个类的接口转换成客户希望的另外一个接口。 就如同是电源适配器将不适用的交流电…

css实现背景渐变叠加

线性渐变效果图: .box{width: 100vw;height: 100vh;background:linear-gradient(to bottom,transparent,#fff 30%),linear-gradient(to right,pink,skyblue);}径像渐变效果图&#xff1a; .box{width: 100vw;height: 100vh;background:linear-gradient(to bottom,transparent,#…

【JavaEE初阶】 JVM类加载简介

文章目录 &#x1f343;前言&#x1f332;类加载过程&#x1f6a9;加载&#x1f6a9;验证&#x1f6a9;准备&#x1f6a9;解析&#x1f6a9;初始化 &#x1f384;双亲委派模型&#x1f6a9;什么是双亲委派模型&#xff1f;&#x1f6a9;双亲委派模型的优点 ⭕总结 &#x1f343…

Vue.js 实用技巧:深入理解 Vue.mixin

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

开发一套小程序所需的费用取决于多个因素

随着移动互联网的发展&#xff0c;小程序已经成为许多企业和个人推广业务和服务的重要工具。 不过&#xff0c;对于很多想要开发小程序的人来说&#xff0c;最大的疑问就是开发一套小程序要花多少钱。 这个问题的答案并不是固定的&#xff0c;因为开发一个小程序的成本取决于几…