内存模型问题
- 空类和空结构体的
sizeof:- 在C++中,一个空类(
class)或空结构体(struct)没有任何数据成员时,其sizeof为1字节。 - 这是因为C++要求每个对象占用至少1字节的空间,以确保每个对象有唯一的内存地址。
- 在C++中,一个空类(
- 类和结构体的相同点:
- 在C++中,
class和struct在内存布局和功能上几乎等价,唯一的区别是默认访问权限:class默认是private。struct默认是public。
- 因此,空类和空结构体的
sizeof行为完全一致。
- 在C++中,
- 添加普通成员函数:
- 为空类或空结构体添加普通成员函数(包括构造函数、析构函数等)不会改变
sizeof,仍为1字节。 - 原因:成员函数是类的行为,存储在代码段中,不占用对象实例的内存。
- 为空类或空结构体添加普通成员函数(包括构造函数、析构函数等)不会改变
- 添加虚函数:
- 当空类或空结构体添加第一个虚函数时,
sizeof会增加到虚表指针(vptr)的大小:- 32位系统:通常为4字节。
- 64位系统:通常为8字节。
- 添加多个虚函数不会进一步增加
sizeof,因为只需要一个虚表指针指向包含所有虚函数地址的虚表。
- 当空类或空结构体添加第一个虚函数时,
- 结构体支持成员函数:
- C++中的
struct可以像class一样添加各种成员函数(普通函数、构造函数、析构函数、虚函数等),并支持面向对象特性(如继承和多态)。 - 这是C++对C语言
struct的扩展,使其功能与class等价。
- C++中的
- 关键结论:
- 空类和空结构体的
sizeof默认是1字节。 - 普通成员函数不影响大小,虚函数引入虚表指针后大小变为4或8字节(取决于平台)。
- 无论
class还是struct,添加多个虚函数只增加一个虚表指针的开销,不会随虚函数数量线性增长。
- 空类和空结构体的
结构体对齐
- 由于系统资源分配的问题,结构体占用的内存字节数并不总是所有的结构体成员的内存之和,而是会大于等于结构体成员的内存,便于提高运行效率
- 运行结果总是结构体中对齐要求的整数倍
- 对齐的要求为min(8, 最大成员占用的的字节数),8是指的64位系统
#include <iostream>
using namespace std;
struct s1
{
char c1; //1b 0
int i; // 4b 4
char c2; //1b 8
};
struct s2
{
char c1; // 1b 0
char c2; // 1b 1
int i; //4b 4
};
struct s3
{
char c1; //1b 0
int i; // 4b 4
char c2; //1b 8
char c3; //1b 9
};
int main(int argc, char const *argv[])
{
cout << sizeof(s1) << " " << sizeof(s2) << " " << sizeof(s3) << endl;
//打印偏移量
cout << offsetof(s3, c1) << " " << offsetof(s3, i) << " " << offsetof(s3, c2) << " " << offsetof(s3, c3) << endl;
return 0;
}
-
运行结果
12 8 12
0 4 8 9
-
对于不同位数的成员,只能存放在指定位置:char 0 1 2 3… int 0 4 8 12… double 0 8 16
-
所以结构体的利用规则:体积小的永远零接着放,便于节省空间
-
对于嵌套的结构体,需要仔细辨认,结构体嵌套,嵌套的结构体对齐到自己的最大对齐数,将结构体放入新的结构体,新结构体对齐到所有的最大对齐数(把嵌套的结构体当成员考虑)
#include <iostream>
struct s1
{
double d;
char c;
int i;
}; //16
struct s2
{
char c1; //0
struct s1 s;
double d;
};
/*
struct s2
{
char c1; //0
//s1的代码
double d; //8
char c; //16
int i; //20
double d; //24
-->24+8 = 32
};
*/
int main(int argc, char const *argv[])
{
std::cout << "sizeof(s1): " << sizeof(s1) << std::endl;
std::cout << "sizeof(s2): " << sizeof(s2) << std::endl;
return 0;
}
-
运行结果
sizeof(s1): 16
sizeof(s2): 32 -
通过宏指定对齐数#pragma pack(1),指定对齐为1字节(老版本)
-
新版本用alignas()或者alignattribute,不同的编译器标准不同

被折叠的 条评论
为什么被折叠?



