各位好友,欢迎来到本期博文 !本期,继续推进上一期内容 !

-------> 结构体

下面重点讲解, 如何计算一个结构体的大小

现定义一个结构体,如下 :>

C++ ---->类 ~~ 对象_03_this 指针特性

1. 内存对齐规则

(1)第一个成员在于结构体偏移量为 0 的地址;

(2)其他成员变量要对齐到某一个数字(对齐数)的整数倍的地址处;

注意:> 对齐数 = 编译器默认的一个对齐数 与 该成员字节大小的较小值;  VS 默认对齐数的大小为  8

(3)结构体总大小为:最大对齐数(所有变量类型最大值与默认对齐参数取最小值)的整数倍;

(4)如果 嵌套了结构体,嵌套的结构体对齐到自己最大对齐数默认的整数倍,结构体的整体大小就是所有最大对齐数(包含嵌套的结构体)整数倍 !

2. 计算结构体大小(重点

为了方便好友们,有更好的观感,与更好地理解 !以下分析,均是采用彩色图示,请观察:>

C++ ---->类 ~~ 对象_03_结构体大小计算_02

以上就是,结构体大小的相关计算了 !

其实,只要学会了方法,无论 怎样变化 变量类型,以及 成员个数,总能应付自如 !😊

-------> this 指针

各位好友,先来看看下面的代码实现 !开启“this”指针战斗,这需要有相对应的切入点 ! 如下所示:

#include <iostream>
using std :: cout;
using std :: endl;

struct 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, d2;
  
  d1.Init(2023, 05, 01);
  d2.Init(,2023, 05, 02);
  
  d1.Print();
  d2.Print();
	return 0;
}

为了方便好友们,有更好的观感体验,与更好的理解,现附上有彩色的代码图样 :>

C++ ---->类 ~~ 对象_03_结构体大小计算_03


请观察上述代码:为什么,打印函数都没有入参数,最终却 打印出了正确的结果!以及,打印函数是如何区分不同的对象 d1 与 d2 的?其实,这是 “ this ”指针 运用 !

C++ 中通过引入 this 指针,使得 C++ 编译器给每个 “非静态的成员函数” 增加了一个隐藏的指针参数,让该指针指向当前对象(即函数调用的时候访问的对象

在函数体 所有 "成员变量"的操作,都是通过该指针去访问的。 如此,用户不需要传递实参,编译器自动完成 !

也是说,由以前的手动挡变换成了自动挡 !这也是 C++  优化处理函数的表现之一 !更高效,更加惹人喜爱 !😊

-----> this 指针是否可以显示 --->可以部分显示  -->如下 :>

C++ ---->类 ~~ 对象_03_this 指针特性_04

如果 在参数部分展现出来 是否可行呢 ? 

----->如下 :>

C++ ---->类 ~~ 对象_03_结构体大小计算_05

请注意观察,上述红色标注点 !此时,一定要注意 const 位置,表明  const 修饰指针本身,this 指针指向的内容可以被修改 !现理解 上述参数部分:>本类名下的 this 指针类型 。一定别忘了,要加一个 const 进行修饰 !

因为,this 指针是一个关键字,无法被修改 !

由 上述图示可知, this 指针不能在形参部分显示出来,但可以在函数体内部显示出来 !

上述,“ this ” 指针实现日期显示,已经完成 !下面讲述 “ this ” 指针特性 !

------->“ this ” 指针特性

(1)this 指针类型:类的类型* const, 即成员变量函数中,不能给 this 指针赋值 ;

(2)只能在 “成员函数” 内部实现;

(3)this 指针,本质是 “成员函数”的形参。

  当对象调用成员函数时,将对象地址作为实参传递给 this 形参。总之,对象中不存储 this 指针 ;

(4)this 指针是 “ 成员函数 ” 第一个隐含的指针形参。一般情况下,由编译器 通过 ecx 寄存器自动传递,不需要    用户传递 。

那么,上述结论中,该如何理解 特性 (4)呢 ?显然要用到反汇编,看底层逻辑,如下所示 :>

C++ ---->类 ~~ 对象_03_结构体大小计算_06


在了解反汇编之前,首先 会有疑问, this 指针,存储在哪里 ?

以上部分,讲解 this 指针的错误用法,得知 不能在参数部分进行显示,一个函数的参数显然在 栈区 !

因此, this 指针是跟普通参数一样存在于函数调用的栈区里面 !上述反汇编中出现的 “push” 就是 压栈 之意 !

下面,请观察反汇编 !VS 内部对 this 指针进行优化,对象的地址放在 ecx ,而寄存器 ecx 存储 this 指针的值

接下来,测试 this  指针 是否可以为 ,如下 :>

C++ ---->类 ~~ 对象_03_this 指针_07

此时程序正常运行

----->d1 调用Print,不会发生解引用,因为Print的地址不在对象中, d1 作为实参传递给 this 指针

同时, this 指针是空的,但是函数内部没有对指针进行解引用 !显然是可行的 !

C++ ---->类 ~~ 对象_03_this 指针特性_08

此时程序运行崩溃

----->d1 调用 Print() 函数,不会发生解引用,因为 Print() 函数地址不在对象中。 d1会作为实参传递给 this指针

同时, this 指针为空,但函数内部访问  _a,  本质上是  this -> _a   显然程序出现了  Bug !

C++ ---->类 ~~ 对象_03_结构体大小计算_09

上述,this 指针为空的时候,不光不能传递,还不能显示;

注意,A 是类名,不存在 空间; 声明类之后, 创建的对象,才会具有空间 !这在前期博文有讲解 !不清楚的好友可以自行查看之前的博文 !😊

其实, this 指针的运用,隐藏 是很新颖的!之前 用 C++ 实现栈区,发现了好多函数同样没有传参,但却能运行

至于原因,想必好友们,已经得知了 !很香的 C++ 栈区实现,同样有隐藏版的指针 !😊😊

以上就是本期博文,新的玩法, this 指针 !隐藏 或成为开发项目中 必不可或缺的一点 !

至此,本期博文,已完结!希望本期博文,为好友们带来了 新的体验 !下一期,仍然是 继续推进 大类 大对象

敬请期待 !感谢你的阅读 !  希望 C++ 领域能使你绽放光彩 !😊😊