「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」
💦 如何计算类对象的大小
#include<iostream>
using namespace std;
struct QueueNode
{
QueueNode* next;
int val;
};
class Queue
{
public:
void Init();
void Push(int x);
void Pop();
private:
QueueNode* head;
QueueNode* tail;
};
int main()
{
Queue q1;
q1.Init();
q1.Push(1);
q1.Push(2);
q1.Push(3);
Queue q2;
q2.Init();
q2.Push(1);
cout << sizeof(q1) << endl;
cout << sizeof(q2) << endl;
return 0;
}
❓ q1 和 q2 的大小 ❔
q1 和 q2 一样大,这里不要被它们 Push 了多少个数据所迷惑了,这些 Push 的数据都在堆上 malloc 空间存储,q1 和 q2 只是在栈上存储了指针指向堆里,所以不管 Push 了多少个数据,它的大小都是相同的
就像设计图和房子,一个房子住三个人,另一个房子住一个人,不会影响图纸的大小
注意类是不占内存空间的,它在编译前是放在文件里的,存在磁盘上。编译后,变成指令存在公共代码段;它定义的对象才会占用内存空间。算类型的大小就等同于算类型定义的对象的大小
Queue 里有三个函数二个变量,所以共计 20 Byte ❔
实际上不是,q1 和 q2 的大小在 32 位平台下是 8 Byte,好像是说对象里只存储了成员变量的大小
实际上在计算类型大小或者类对象时,只考虑成员变量,因为对象中只存了成员变量,没有存成员函数
💦 类对象的存储方式猜测
💨 方案一:对象中包含类的各个成员
缺陷:每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。
💨 方案二:只保存成员变量,成员函数存放在公共的代码段
❓ 观察下面类的大小是多少 ❔
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{}
private:
int i;
char ch;
};
//没有成员变量的类
class B
{
public:
void Print()
{}
};
//空类
class C
{};
int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl;
return 0;
}
📝 说明:
这里 A 占 8 个字节 (同结构体内存对齐)、B 占 1 个字节、C 占 1 个字节
没有成员变量的类/空类为啥是 1 个字节,难道不是 0 吗 ❓
我们说了实际上在计算类型大小或者类对象时,只考虑成员变量,那它没有成员变量,应该是 0。但是这个地方不能是 0, 注意计算类型的大小本质上是算这个类型定义变量的大小。如果一个类没有成员,那么它的对象需要给 1 Byte 进行占位来标识对象的存在 —— C c1,c2; (如果没有空间你怎么表示 c1、c2 存在) ,这 1 字节不存储有效数据
❓ 没有成员变量的类和空类有什么意义 ❔
目前看不到这样的场景,以后学到仿函数和 STL 的时候就能体现了。
💦 结构体内存对齐规则
【结构体相关面试题】
1、 结构体怎么对齐? 为什么要进行内存对齐?
2、如何让结构体按照指定的对齐参数进行对齐
3、什么是大小端?如何测试某台机器是大端还是小端,有没有遇到过要考虑大小端的场景
结构体在 C 语言部分就学习了,这里就不细讲了,附上链接