C++相关概念和易错语法(3)(类的声明和定义、空指针分析、this指针)

news2024/11/20 7:14:13

1.类的声明和定义

注意类的声明和定义分离的时候,在定义处要使用域作用限定符,否则函数声明链接时的定位不到函数的定义。

1b2a658133f843b588e0ef27bacdcf35.png

这些成员变量、函数的作用于这个类域,将功能集成在一起,这体现出封装的思想。

在区分类的定义和声明时,主要看有没有开辟空间

fadb2f62b8bc430f82d64960ba7f5010.png

在.h文件中,成员变量和成员函数都算作声明,只有在创建这个类的时候,才会为成员变量创建空间。但是,成员函数并不会被拷贝。这样可以防止空间的浪费。

为形象理解,可以将类的声明视为图纸,这个图纸可以实例出多个对象。

583ad0aee8564309afff382382f878c9.png

因此在计算对象的大小时,只会计算成员变量的大小,同时满足和结构体一样的对齐操作,当然你也可以用#pragma pack(1)来设置默认对齐数。

abb5da0e062d44e58ff06c7aa48757b4.png

注意这是64位平台测试,指针的大小是8个字节。

我们可以将成员函数视为类的公共区域,每个成员调用成员函数都是直接到类里面来找。注意刚刚的描述是便于形象理解成员函数的调用,和访问限定符(protected、struct默认公有public,class默认私有private,只要不写public都是私有)不同,不要混淆。208ae056096c408fadbedd86587e12ba.png

2.因空指针导致的程序崩溃

解释下面代码为什么不报编译错误:

f324d9a4ade44dc4bc26a3aa977393e8.png

我们需要通过编译的过程来解释这一现象:

cf54f11a320b4ebeab67bc931a3c052f.png

预处理是将所有的宏和头文件展开,生成的文件我们仍然能读懂。

编译是检查语法错误,语义是否能被正确解读。在这里,nullptr的使用并没有导致语法的错误,也不会产生歧义,所以编译这里不会报错。

汇编是将所有代码转化为二进制的机器指令。

 

同样,在链接时也不会出现问题,生成可执行程序。

2c8fc04bb2b749158c11caf25be24040.png

最终是因为越界访问导致程序崩溃。

注意导致程序崩溃的原因是对空指针的指向区域进行的访问或修改。如果不进行这些操作,那么就是可行的。引用就是个很好的例子。

49b2bf8382bc4d2797ee70ae58b23e66.png

因为引用的语法和实质层面的不一致,导致这里很容易被误解为对a进行了访问但因为引用的实质是指针,所以这里只是将a的值nullptr赋给了b,并没有对nullptr产生访问行为,所以这里的程序不会有任何问题。

669b1a8949fa435fa0a80110ea875e29.png

在观察程序崩溃时,先看语法层面上是否造成歧义,导致编译错误;再看要使用的函数是否都成功定义且定位,这关系到链接错误;最后从汇编的角度来看程序是否发生了越界访问等。

3.不同的this指针区分不同的对象

this是一个关键字。它是隐含在类中的一种指针,在对该类实例化出多个对象时,this指针就用来给每个对象贴上标签。

为了理解它,先看一段代码,解释为什么两次调用Add时都没有传参,但在类里面调用函数时还是能区分不同的对象:


#include <iostream>
using namespace std;

class C
{
public:

	void Init(int a = 0, int b = 0, int c = 0)
	{
		_a = a, _b = b, _c = c;
	}

	void Add()
	{
		cout << "add:" << _a + _b + _c << endl;
	}


private:

	int _a;
	int _b;
	int _c;
};

int main()
{
	C c1, c2;

	c1.Init(1, 2, 3);
	c2.Init(4, 5, 6);
	c1.Add();
	c2.Add();

	return 0;
}

结果是:

e366a1ee1fda40539969e4c09dd632db.png

其中虽然我们看上去没有传参,但是在汇编代码中我们就可以看到实际上Init和Add都多传了一个参数,这个参数就是this指针,在这里它的类型是C* const c1,C* const c2:

bcc4ad6f55be4795b92b2be5c4e36d35.png

70db2ff4719d43828331662fdfec1213.png

在代码语义上,它们相当于在参数中,多传了一个类的指针:

24f152a837b24123a120b93efabbebfb.png

e529727515bf495c92f9340fb7d87216.png

在实际写代码的时候,虽然this指针实际存在,但参数中却不能写this,因此这里使用注释来表示实际的执行情况。但是,在成员函数内部,可以显式写出this指针,因为this指针其实是类的指针,而类又和struct同源,所以用的是this->形式。

又因为this是成员的标签,它也不能随便更换其指向。

6602a6658e09482e9e60f6a4bd363687.png

 

this指针可能存在栈中,也可能存在寄存器中,不同编译器有不同的做法。但this指针都不会存在成员中。这可以用空类来进行验证。

b301fbf6401c46a2ac6fb6cb8c9d2440.png

如果指针确实存在成员中,那么这个类的大小至少是8(64位),所以this指针是单独在栈或寄存器存放的。而空类的大小为1是作为创建类成功的标志,对于没有成员变量的类都是如此

4.this指针为空指针的代码解读

先来看一段代码


#include <iostream>
using namespace std;

class C
{
public:
	void Print()
	{
		cout << "Hello,world!" << endl;
	}
private:
	int _a;
};

int main()
{
	C* c1 = nullptr;

	c1->Print();

	return 0;
}

运行结果是:

2176d1f027ec4888ac87a4ed853ee344.png

可以看出这个代码执行没有任何问题。

这要结合上面第2点对空指针的分析方法来判断。分析如下图:

425fab13e4ce4694a86eb4cc87eba162.png
 

 

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

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

相关文章

C# WPF编程-元素绑定

C# WPF编程-元素绑定 将元素绑定到一起绑定表达式绑定错误绑定模式代码创建绑定移除绑定使用代码检索绑定多绑定绑定更新绑定延时 绑定到非元素对象Source属性RelativeSource属性DataContent属性 数据绑定是一种关系&#xff0c;该关系告诉WPF从源对象提取一下信息&#xff0c;…

深度学习pytorch实战第P2周:CIFAR10彩色图片识别

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/0dvHCaOoFnW8SCp3JpzKxg) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊](https://mtyjkh.blog.csdn.net/)** 零、引言&#xff08;温故而知新&#xff…

什么是ICMP协议,如何防护ICMP攻击

一.什么是ICMP ICMP&#xff08;Internet Control Message Protocol&#xff09;是互联网控制报文协议&#xff0c;是TCP/IP协议族的一个子协议。它主要用于在IP网络中传递控制信息和错误消息&#xff0c;是IP协议的补充。ICMP协议是一种无连接协议&#xff0c;它不需要建立…

SambaNova 芯片:深入解析其架构和高性能秘诀

SambaNova——一家总部位于帕洛阿尔托的公司已经筹集了超过10亿美元的风险投资&#xff0c;不会直接向公司出售芯片。相反&#xff0c;它出售其定制技术堆栈的访问权限&#xff0c;该堆栈具有专门为运行最大的人工智能模型而设计的专有硬件和软件。 最近&#xff0c;SambaNova…

MySQL - 基础三

11、事务管理 CURD不加控制&#xff0c;会有什么问题&#xff1f; 当客户端A检查还有一张票时&#xff0c;将票卖掉&#xff0c;还没有执行更新数据库时&#xff0c;客户端B检查了票数&#xff0c;发现大于0&#xff0c;于是又卖了一次票。然后A将票数更新回数据库。这是就出现…

面经分享(Flask,轻量级Web框架)

1. Flask的核心特点 a. 轻量级&#xff1a;核心简洁&#xff0c;只提供了基本的功能&#xff0c;其他高级功能可以通过插件或扩展来添加。 b. 灵活性&#xff1a;允许开发者选择适合自己项目的组件和工具&#xff0c;没有强制的项目结构和设计模式。 c. 易于扩展&#xff1a;提…

OPPO VPC 实践探索

01 概述 一年前(20年6月)&#xff0c;OPPO云网络技术底座开始支持VPC方案&#xff0c;解决了用户担心的云上安全和虚拟实例的性能问题。我们称这个版本为VPC1.0&#xff0c;其采用了先进的智能网卡加速和VXLAN隧道隔离技术&#xff0c;实现了VPC从无到有的突破。 然而由于业务快…

FreeRtos入门-3 信号量(计数值、二进制、互斥量、递归锁)

信号量 计数量 二进制 互斥量 递归锁 创建 xSemCalc xSemaphoreCreateCounting(10, 0);//计数最大值10&#xff0c;初始值0 xSemUart xSemaphoreCreateBinary(); xSemUART xSemaphoreCreateMutex(); xSemUART xSemaphoreCreateRecursiveMutex(); 释放 xSemaphore…

mysql 判断一张表是否存在的方法

查询表是否存在 使用 SHOW TABLES SHOW TABLES LIKE %tbl_tabl%;结果: 查询 INFORMATION_SCHEMA // like 匹配 SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA test AND TABLE_NAME like %tbl%; // 完全匹配 SELECT TABLE_NAME FROM INFORMATION_SC…

JVM基础二——类的生命周期

加载阶段 &#xff1a; 连接阶段&#xff1a; 初始化阶段&#xff1a; 总结&#xff1a;

C++ | Leetcode C++题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isMatch(string s, string p) {int m s.size();int n p.size();auto matches [&](int i, int j) {if (i 0) {return false;}if (p[j - 1] .) {return true;}return s[i - 1] p[j - 1];};vector<…

计算机网络——数据链路层(流量传输与可靠传输机制)

计算机网络——数据链路层&#xff08;流量传输与可靠传输机制&#xff09; 流量传输与可靠传输机制流量控制可靠传输机制 停止-等待协议无差错情况接收并检测到差错状态确认丢失或迟到状态 停等协议的效率分析后退N帧协议&#xff08;Go-Back-N&#xff0c;简称GBN&#xff09…

KnowLog:基于知识增强的日志预训练语言模型|顶会ICSE 2024论文

徐波 东华大学副教授 东华大学计算机学院信息技术系副系主任&#xff0c;复旦大学知识工场实验室副主任&#xff0c;智能运维方向负责人。入选“上海市青年科技英才扬帆计划”。研究成果发表在IJCAI、ICDE、ICSE、ISSRE、ICWS、CIKM、COLING等国际会议上&#xff0c;曾获中国数…

Linux 内核优化简笔 - 高并发的系统

简介 Linux 服务器在高并发场景下&#xff0c;默认的内核参数无法利用现有硬件&#xff0c;造成软件崩溃、卡顿、性能瓶颈。 当然&#xff0c;修改参数只是让Linux更好软件的去利用已有的硬件资源&#xff0c;如果硬件资源不够也无法解决问题的。而且当硬件资源不足的时候&am…

小红的平滑值插值【牛客周赛38】

题目描述&#xff1a; 小红定义一个数组的“平滑值”为&#xff1a;相邻两数差的绝对值的最大值。 具体的&#xff0c;数组a的平滑值定义为 现在小红拿到了一个数组。她每次操作可以在两个元素之间添加一个整数&#xff08;不能添加在第一项前面或者最后一项后面&#xff09;。…

鸿蒙开发第一课-工具与HelloWorld

武汉数字人才实训基地 一、初始HarmonyOS以及DevEco Studio 2023年8月4日&#xff0c;HarmonyOS 4.0操作系统正式发布。华为鸿蒙Next&#xff08;HarmonyOS Next&#xff09;操作系统开发者预览版(Developer Preview)发布。超过7亿台设备搭载了HarmonyOS 系统 2024年&#xf…

时序预测 | Matlab基于CFBP级联前向BP神经网络时序预测

时序预测 | Matlab基于CFBP级联前向BP神经网络时序预测 目录 时序预测 | Matlab基于CFBP级联前向BP神经网络时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab基于CFBP级联前向BP神经网络时序预测&#xff08;完整源码和数据)&#xff1b; 2.数据集为excel…

提灯定损的建模-UMLChina建模知识竞赛第5赛季第9轮

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 参考潘加宇在《软件方法》和UMLChina公众号文章中发表的内容作答。在本文下留言回答。 只要最先答对前3题&#xff0c;即可获得本轮优胜。 如果有第4题&#xff0c;第4题为附加题&am…

阿里 对象存储OSS 云存储服务

1.简介 对象存储服务(Object Storage Service ,OSS) 是一种 海量、安全、低成本、高可靠的云存储服务&#xff0c;适合存放任意类型的文件。容量和处理能力弹性扩展&#xff0c;多种存储类型供选择&#xff0c;全面优化存储成本。 2.如何使用。参考文档 看文档&#xff0c;说的…

LeNet卷积神经网络

文章目录 简介conv2d网络层的结构 简介 它是最早发布的卷积神经网络之一 conv2d 这个卷积成的参数先进行介绍一下&#xff1a; self.conv1 nn.Conv2d(in_channels3, out_channels10, kernel_size3, stride1, padding1)先看一下in_channels 输入的通道数&#xff0c;out_cha…