【C++】类和对象初探:类的实例化与对象生命周期管理,解析this指针的奥秘

欢迎来到CILMY23的博客

本篇主题为: 类和对象初探:类的实例化与对象生命周期管理,解析this指针的奥秘

个人主页:CILMY23-CSDN博客

系列专栏:Python | C++ | C语言 | 数据结构与算法

感谢观看,支持的可以给个一键三连,点赞关注+收藏。


写在前头:

本文是继上篇的续文,可以从类和对象初探开始看。

链接:  

C语言转型之路:从C到C++的类与对象初探-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/sobercq/article/details/137756562?spm=1001.2014.3001.5501


目录

 一、类和对象

1.6 类的实例化

1.7 类对象模型

1.7.1 类对象的大小

1.7.2 类对象的存储方式 

1.7.3 特殊类的大小 

1.8 this指针

1.8.1 this 指针的概念 

1.8.2 this 指针的特性

1.8.3 this指针存在位置 

1.8.4 this指针可以为空吗


 一、类和对象

1.6 类的实例化

当谈到类的实例化时,通常指的是创建类的对象,即在内存中为该类分配存储空间,并创建对象实例的过程。

  1. 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没 有分配实际的内存空间来存储它,比如:入学时填写的学生信息表,表格就可以看成是一个 类,来描述具体学生信息。
  2. 类就像谜语一样,对谜底来进行描述,谜底就是谜语的一个实例。谜语:"年纪不大,胡子一把,主人来了,就喊妈妈"   谜底:山羊
  3.  一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量 
  4. 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设 计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象 才能实际存储数据,占用物理空间
  5. 类用private限制的成员变量是声明,不是定义,定义是需要开空间,而声明不占用实际的物理空间

 对上述第五点我们来延申讲解一下:

假设我们有个日期类举例,我们在main函数中是无法访问year的,这说明它可能是个声明,也可能是个定义,从语法上,private就限制了访问,那我们把权限打开。 

 权限放开后,我们仍然看到以下情况:

 通过上述情况我们知道,无论是公有还是私有,类中的成员变量仍然是无法访问的,而我们可以访问d1.year++,这是因为类的实例化,创建了d1对象,才开辟了空间,从而能将year++。

1.7 类对象模型

类对象模型(Class Object Model,COM)是描述C++编译器如何在内存中组织和管理类和对象的底层机制的概念。COM 描述了类成员变量和成员函数的布局方式方法的调用方式以及派生和多重继承等问题。

它是 C++ 语言规范和实现之间的桥梁,对于理解面向对象编程的中间表示形式。

1.7.1 类对象的大小

 类对象的大小遵循C语言中结构体内存对齐规则(内存对齐可以看链接),所以我们看以下的日期类

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Init(2024, 04, 20);cout << sizeof(d1) << endl;return 0;
}

我们知道成员变量遵循内存对齐规则,那这个类要开辟空间就需要十二字节那函数到底算不算在内? 对象的大小要不要加两个指针?这就涉及下一个问题,类对象是如何存储的?

1.7.2 类对象的存储方式 

我们通过汇编来看,相同的函数,他们call的地址是一样的,这说明类的对象函数并没有单独开辟空间,而是共用一个空间

所以我们有两种方案设计,一种是类中有成员变量和成员函数地址,一种是类中有成员变量,在一个公共区域去存储成员函数地址

方案一: 类中有成员变量和成员函数地址

方案二: 一个公共区域去存储成员函数地址

 那C++选择了第二种方式,为什么?

 对于方案一,每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,就会浪费空间。而代码只保存一份,在对象中保存存放代码的地址,也是同理。因此选择了方案二。

 因此来回答第一小节中的问题

那这个类要开辟空间就需要十二字节那函数到底算不算在内? 对象的大小要不要加两个指针?

答案显而易见,这个类是十二字节大小函数不算在内,对象的大小不需要加两个指针。 

1.7.3 特殊类的大小 

接下来还有两个特殊类的大小:

class A1
{
public:void f1(){}
};class A2
{};cout << sizeof(A1) << endl;cout << sizeof(A2) << endl;

 结果:

这两个类都是没有成员变量的类,它们的大小理论来说都是0,而这里给了1字节,如果没有空间的话,就无法实例化,所以可以理解为是一个规定,是一个占位,标识对象实例化时,定义出来存在过。

1.8 this指针

1.8.1 this 指针的概念 

 首先我们先通过一个日期类来看一个例子

 有个问题,为什么d1对象打印的是0417,d2对象打印的是0418,明明二者用的都是相同的函数

这里面其实就涉及了一个C++中隐含的 this 指针。

C++编译器给每个“非静态的成员函数“增加了一个隐藏的 this 指针参数,这个 this 指针是一个指向当前对象(函数运行时调用该函数的对象)的指针,它是类的成员函数中的一个隐式参数。当类的成员函数被调用时,this 指针被自动传递给成员函数,指向调用该函数的对象实例。通过 this 指针,成员函数可以访问调用它的对象的所有成员变量和成员函数。

注意:this 指针是成员函数的第一个参数

例如:成员函数被编译器自动处理成如下形式

void Print(Date* const this)
{cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
}

 而调用的地方会被编译器处理成如下形式:

d1.Print(&d1);
d2.Print(&d2);

1.8.2 this 指针的特性

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

1.8.3 this指针存在位置 

根据上面的基本四点,我们可以了解this指针了,但有个问题,this指针不存在对象中,那存在哪里?

 a.堆  b.栈  c.静态区  d.常量区 e.对象中

 答案是b,因为this指针是函数的形参。

 

这里就必须掏出我们熟悉的内存区域划分图了, 过去我们在讲C语言动态内存分布的时候说过,栈区是局部变量和形式参数的区域,堆区是动态内存区域,静态区是数据段,这里是存放全局变量和静态数据的地方,常量区也就是代码段。

现在我们就将其整理详细点:

所以对this指针存的位置我们马上就可以分辨出来了,因为this指针是函数的形式参数,所以它存在栈上。

1.8.4 this指针可以为空吗

 首先我们来看一段代码

 下面程序编译运行结果是?  A、编译报错  B、运行崩溃  C、正常运行 

class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}

 答案是:正常运行

我们接着再看下一段代码: 

下面程序编译运行结果是?  A、编译报错  B、运行崩溃  C、正常运行 

class A
{
public:void PrintA(){cout << _a << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->PrintA();return 0;
}

答案是: 运行崩溃

 这就涉及到 -> 会不会解引用的问题了

第一种情况,-> 不会解引用,因为 Print 不在 p 的空间内,此时它的意义就是给 this 指针传了 p 的地址,此时 this 指针是空指针,假设 _a 存在 p 的空间,是公有的,那么 -> 就会选择对 this 指针解引用,因为它要到 p 的空间里去找  _a ,所以此时就会报错,那么同理第二个 PrintA 就会运行崩溃。

总结:空指针的传递并不会发生问题,而空指针的访问会出现问题。  


 总结:

  • 类的成员变量是声明,不是定义,定义是需要开空间,而声明不占用实际的物理空间
  • 类的实例化是开辟空间,创建对象
  • 类的成员变量大小遵循结构体内存对齐原则
  • 一个类的大小,实际就是该类”成员变量”之和,遵循内存对齐。
  • 空类的大小,空类比较特殊,编译器给了空类1个字节来唯一标识这个类的对象。没有成员变量的类也是如此。
  • 内存对齐可以指定对齐数,用 #pragma pack()就可以指定对齐数
  • 编译器搜索从局部到全局
  • 关于this指针有以下四点
  1. 形参和实参的位置,我们不能显示写
  2. 成员函数内部可以使用
  3. this指针存在栈上,因为它是形式参数
  4. this指针在某些编译器如vs上会用寄存器传递,这是为了提高效率
  •  -> 会不会解引用,这还要取决于它要得到什么。

结构体内存对齐规则:

1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数  与  该成员大小的较小值
VS中默认的对齐数为8
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。 


感谢各位同伴的支持,本期C++篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。 

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

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

相关文章

医学影像图像去噪:滤波器方法、频域方法、小波变换、非局部均值去噪、深度学习与稀疏表示和字典学习

医学影像图像去噪是指使用各种算法从医学成像数据中去除噪声,以提高图像质量和对疾病的诊断准确性。MRI(磁共振成像)和CT(计算机断层扫描)是两种常见的医学成像技术,它们都会受到不同类型噪声的影响。 在医学影像中,噪声可能来源于多个方面,包括成像设备的电子系统、患…

[RTOS 学习记录] 工程管理工具make及makefile

[RTOS 学习记录] 工程管理工具make及makefile 这篇文章是我阅读《嵌入式实时操作系统μCOS-II原理及应用》后的读书笔记&#xff0c;记录目的是为了个人后续回顾复习使用。 前置内容&#xff1a; 开发工具 Borland C/C 3.1 精简版 文章目录 1 make 工具2 makefile 的内容结构3…

MLLM | InternLM-XComposer2-4KHD: 支持336 像素到 4K 高清的分辨率的大视觉语言模型

上海AI Lab&#xff0c;香港中文大学等 论文标题:InternLM-XComposer2-4KHD: A Pioneering Large Vision-Language Model Handling Resolutions from 336 Pixels to 4K HD 论文地址:https://arxiv.org/abs/2404.06512 Code and models are publicly available at https://gi…

使用 ollama 部署最新的Llama 3 70B本地模型

一、ollama是什么? 在本地启动并运行大型语言模型。运行Llama 3&#xff0c;Mistral, Gemma, Code Llama和其他模型。自定义并创建您自己的。 综合优点&#xff1a; 快速下载容器自动运行大模型&#xff0c;现在下载&#xff0c;马上上手。本地利用 cpu 运行大模型&#xff0c…

【Hadoop】-Apache Hive概述 Hive架构[11]

目录 Apache Hive概述 一、分布式SQL计算-Hive 二、为什么使用Hive Hive架构 一、Hive组件 Apache Hive概述 Apache Hive是一个在Hadoop上构建的数据仓库基础设施&#xff0c;它提供了一个SQL-Like查询语言来分析和查询大规模的数据集。Hive将结构化查询语言&#xff08;…

视频教程下载:ChatGPT驱动的SEO、网络营销、生产力提升

用户遇到的一个常见问题是在ChatGPT对话过程中难以保持清晰的目的和专注。这可能导致互动无效和浪费时间。这门课程将教给各种创意人士——艺术家、制造者、博主、讲师和内容创作者——如何制定理想的提示配方&#xff0c;从而产生更有成效的对话和更高的回报。 这是一门关于如…

【入门篇】本章包括创建云项目、数据库的使用、云存储管理、云函数的基本使用、实战举例(小程序之云函数开发入门到使用发布上线实操)

云函数 云函数相当于服务器接口的概念,它并属于小程序端代码。它是以函数的形式运行后端代码来响应事件以及调用其他服务。运行环境是Node.js。 一、基创建云函数项目 打开微信开发者工具: 打开微信开发者工具,并登录你的微信开发者账号。 创建项目: 如果还没有创建项目,你…

7. Django 模型与数据库

第7章 模型与数据库 Django对各种数据库提供了很好的支持, 包括PostgreSQL, MySQL, SQLite和Oracle, 而且为这些数据库提供了统一的API方法, 这些API统称为ORM框架. 通过使用Django内置的ORM框架可以实现数据库连接和读写操作. 本章以SQLite数据库为例, 分别讲述Django的模型…

Ai-WB2 系列模组SDK接入亚马逊云

文章目录 前言一、准备二、亚马逊云物模型建立1. 注册亚马逊账号&#xff0c;登录AWS IoT控制台&#xff0c;[注册地址](https://aws.amazon.com/cn/)2. 创建好之后点击登录3. 创建物品以及下载证书 三、连接亚马逊云demo获取以及配置1. 下载源码2. 按照顺序执行下面指令3. 修改…

用友U8-Cloud api/hr接口存在SQL注入漏洞

声明&#xff1a; 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 简介 U8 Cloud是由用友推出的新一代云ERP系统&#xff0…

20240331-1-基于深度学习的模型

基于深度学习的模型 知识体系 主要包括深度学习相关的特征抽取模型&#xff0c;包括卷积网络、循环网络、注意力机制、预训练模型等。 CNN TextCNN 是 CNN 的 NLP 版本&#xff0c;来自 Kim 的 [1408.5882] Convolutional Neural Networks for Sentence Classification 结…

hadoop安装记录

零、版本说明 centos [rootnode1 ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)jdk [rootnode1 ~]# java -version java version "1.8.0_311" Java(TM) SE Runtime Environment (build 1.8.0_311-b11) Java HotSpot(TM) 64-Bit Server VM (…

编写一款2D CAD/CAM软件(十六)交互绘制图形

绘制步骤 以交互绘制圆形为例&#xff1a; 点击鼠标左键&#xff0c;确定圆心位置&#xff1b;抬起鼠标&#xff0c;移动鼠标&#xff0c;半径随鼠标位置变化&#xff1b;点击左键确定半径&#xff0c;完成圆的绘制。 绘制结果 Code /// j-operator-create-circle.h#pragma…

Facebook的区块链应用深度分析

去中心化身份验证的意义 在当今数字化社会中&#xff0c;身份验证的重要性不言而喻。对于Facebook这样的大型社交媒体平台来说&#xff0c;确保用户的身份真实性和数据的安全性是至关重要的。传统的中心化身份验证方式存在一定的安全风险和可信性问题&#xff0c;而去中心化身…

verilog中赋值运算符(=和<=)的用法

目录 原理 RTL 图 运算符优先级 原理 “”阻塞赋值&#xff0c;”<”非阻塞赋值。阻塞赋值为执行完一条赋值语句&#xff0c;再执行下一条&#xff0c;可理解为顺序执行&#xff0c;而且赋值是立即执行&#xff1b;非阻塞赋值可理解为并行执行&#xff0c;不考虑顺序&am…

Qt绘制边框有阴影兼容性问题

在Qt开发过程中&#xff0c;有时候我们要显示一个有阴影的对话框&#xff0c;这时一般采用自定义实现&#xff0c;然而最近在开发时软件时&#xff0c;Win11上显示正常&#xff0c;Win10或其他Win11电脑显示不正常&#xff0c;存在兼容性问题吗&#xff1f; 下面是具体的源码 …

【PhpStorm的环境配置与应用的简单介绍】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

Hive架构原理

Hive Hive 的架构是设计用于在大数据环境下进行数据仓库操作和分析的系统。它建立在 Hadoop 生态系统之上&#xff0c;利用 Hadoop 的存储&#xff08;HDFS&#xff09;和计算&#xff08;MapReduce、Tez、Spark 等&#xff09;能力。 1. 元数据存储&#xff08;Metastore&am…

Flutter开发之--初识Flutter

文章目录 概述Flutter整体架构嵌入层引擎层框架层 跑通demo尝鲜Flutter项目的目录介绍Flutter demo项目的运行 总结 概述 Flutter 是由Google公司研发的一种跨端开发技术&#xff0c;在2018年正式推出。Flutter自带Skia图形绘制引擎&#xff0c;采用自绘制的方式&#xff0c;不…