类的大小计算
计算类的大小的时候,也要考虑内存对齐。
class Date
{
public:
void init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void func()
{
cout << "func()" << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.init(2024, 2, 17);
Date d2;
d2.init(2021, 2, 17);
// 可以看出,算出的类型仅仅包括成员变量,而不包含成员函数
cout << sizeof(d1) << endl; // 12
return 0;
}
- 那么为什么成员变量在对象中,而成员函数不在对象中呢?


有上面我们可以看出:每个对象的成员变量是不一样的(因为地址不一样,d1的地址是0x0000004a70affd18, d2的地址是0x0000004a70affd48),==而每个对象调用的成员函数是一样的==(d1和d2对象调用函数有一样的地址),并且把成员函数放在了公共区域(代码段)。
结构体内存对齐
第一个成员在与结构体偏移量为0的地址处。
其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。
VS中默认对齐数是8
结构体总大小为:最大对齐数(所有变量类型最大者与默认对其参数取最小)的整数倍。
如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是
所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
特殊类的大小
// 无成员变量的类
class A
{
public:
void fun(){}
};
// 空类
class B
{};
int main()
{
A a;
B b;
cout << sizeof(a) << endl; // 1
cout << sizeof(b) << endl; // 1
return 0;
}
没有成员变量的类大小都是一个字节。这1byte不存储有效数据只是占位,标识对象被实例化定义出来了。
this指针
引出this指针
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;
Date d2;
// d1和d2都调用了同样的函数,在外面知道是d1还是d2调用。
// 问题:在init函数内部怎么知道2023.10.1是d1的还是d2的年月日呢?
d1.init(2023, 10, 1);
d2.init(2023, 10, 1);
return 0;
}
void init(int year, int month, int day)在编译阶段会被编译器处理成void init(Date* this, int year, int month, int day),这一步只能编译器处理,你不能处理。如下:
class Date
{
public:
void init(Date* this, int year, int month, int day)
{
// this->也是编译器处理
this->_year = year;
this->_month = month;
this->_day = day;
}
};
// 调用的过程编译器也会自己处理
int main()
{
Date d1;
Date d2;
// &d1不能自己写,这是编译器处理的。
d1.init(&d1, 2023, 10, 1);
d2.init(&d2, 2023, 10, 1);
return 0;
}
this指针存在哪里? 首先不存储在对象中。因为计算对象大小的时候,并没有计算
this的大小。 是存储在栈上,因为它是形参,一个隐含的形参。参数都是函数调用时
push到栈上的。