目录
结构体内存对其规则
相关面试题
this指针
相关面试题
结构体内存对其规则
1、第一个成员在与结构体偏移量为0的地址处
2、其它成员变量要对齐到某个数字(对齐数)的整数倍的地址处
对齐数 = 编译器默认对齐数与该成员大小的较小值(vs中默认为8)
3、结构体总大小为:最大对齐数的整数倍
4、如果是嵌套结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍,结构体的整体大小就是所有结构体的最大对齐数的整数倍
相关面试题
1、内存对齐会导致空间闲置,那为什么要进行内存对齐?
①提高读取效率
②硬件(地址总线)规定内存一次读取4(32根线)或8(64根线)个字节
③如果不内存对齐可能会对同一块内存需要多次读取
采用内存对齐:一次读取4个字节,先读取一个字节的i后将其它三个没用的字节丢掉,然后继续读取四个字节的a
不采用内存对齐:一次读取4个字节,先读取i的一个字节和a的前三个字节后将a的前三个字节丢掉,然后继续读取a剩余的一个字节,最后将那三个字节和最后一个字节组合才能得到a,麻烦
2、如何让结构体按照指定的对齐参数进行对齐?
答:#pragma pack(指定对齐数)
this指针
#include <iostream>
using namespace std;
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, d2;
d1.Init(2022, 1, 27);
d2.Init(2022, 2, 28);
d1.Print();
d2.Print();
return 0;
}
Data类中有Init和Print两个成员函数,不论是d1还是d2它们调用的Init函数和Print函数在实现上是一样的,为什么编译器可以做到d1调用Print函数就会打印d1对象的成员变量组成的日期,d2调用Print函数就会打印d2对象的成员变量组成的日期?
这是因为每一个成员函数都会多一个叫this的指针,它是成员函数的第一个参数,那么对于Print函数其实我们可以将其理解成:
void Print(Data* this)
{
cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}
void Print(Data* this,int year,int month,int day)
{
_year = year; //实际上就是this->_year = year;
_month = month; //this->_month = month;
_day = day; //this->_day = day;
}
在调用的时候,编译器也会将其处理成这样的形式:
d1.Print(&d1);
d2.Print(&d2);
即将调用对象的地址当作实参传递给函数
传入谁的地址就访问谁
注意事项:
1、this指针实际上的格式是:类名* const this,即指向的内容可以更改,但本身不能修改
2、形参和实参位置不能显式的写this指针
3、函数内部可以使用this指针
相关面试题
1、this指针存在哪里?堆?栈?静态区?常量区?对象里面?
对象里面(×):计算类的大小时,有三个整型成员变量的类的大小是12字节,如果this指针存放在对象中类的大小应该是大于12的
常量区(×):被const修饰的变量不会存放在常量区,const char*p = "xzxxxxxx"中,p作为指针是存放在栈上的,"xzxxxxxx"是被存放在常量区的,这段代码的意思是将字符串存储的地址给了p,打印p显示出来的就是常量区的地址,被const修饰的变量i的地址和变量j的地址相近,由于变量j是存放在栈上的,可以推出被const修饰的变量i也是存放在栈上的
不加void*强转,p打印出来的就是字符串"xzxxxxxx" ,强转后打印的是字符串的地址
静态区(×):被static修饰的变量和全局变量才存放在静态区
堆(×):calloc、malloc、realloc开辟的才在堆上
栈(√): this指针是成员函数的形参,而形参跟指针一样是存放在栈上的
有些编译器(比如vs)会将this指针存放在寄存器上,频繁访问this指针时效率更高
~over~