C++ 对象模型探索分析之一
大纲
C++ 对象模型
编译器说明
本文所有示例代码均在 Visual Studio 2026(MSVC 编译器)64 位环境下运行。如果使用 Linux 平台的 G++ 编译器,部分示例代码的输出结果可能有所不同。
类对象所占用的内存空间
sizeof 的使用说明
在 C++ 中,只要对象 a 的类型为 A,那么 sizeof(A) 和 sizeof(a) 的计算结果始终相同,与类的复杂程度无关。例如,类中包含成员变量、成员函数、静态成员变量、虚函数等,都不影响这两种写法结果相同这一结论。sizeof 计算的是类对象所占用的内存空间,包括非静态成员变量及可能存在的内存对齐填充,不包括静态成员变量和成员函数本身占用的空间。
空类对象
在 C++ 中,空类和空结构体的对象大小通常都是 1 个字节。
对象大小:
- 空类对象(
class):即使没有任何成员变量和成员函数,sizeof的结果通常是 1。 - 空结构体对象(
struct):与空类对象类似,sizeof的结果通常也是 1。
- 空类对象(
原因分析:
- C++ 标准要求完整对象具有非零大小,以保证不同的独立对象拥有不同的内存地址。
注意事项:
- C++ 中
class和struct的主要区别在于默认访问权限和默认继承权限,不影响空类型对象的大小。 - C 语言标准不允许定义空结构体;GCC 等编译器可能通过扩展支持空结构体,其对象大小通常为 0 个字节。
- C++ 中
1 |
|
带虚函数的对象
C++ 中,类的虚函数不占用类对象内部的数据内存空间(仅占用一个虚函数表指针的额外空间),因为虚函数的函数体代码由该类的所有对象共享,单独存储于程序的代码区(或只读常量区),而类对象内部只存储一个指向虚函数表(vtable)的指针(vptr,32 位系统通常是占用 4 个字节,64 位系统通常是占用 8 个字节),而不是存储虚函数本身的代码;并且,无论类中有多少个虚函数,每个类对象内部永远只有一个虚函数表指针(vptr);但多重继承的情况除外 —— 当一个类继承了多个含有虚函数的基类时,该对象内部通常会包含多个 vptr(每个含虚函数的基类子对象对应一个 vptr)。值得注意的是,虚函数表指针(vptr)是对象级别的,每个对象内部通常只包含一个隐藏的指针,用来指向该类的虚函数表(vtable)。
1 |
|
带成员函数的对象
C++ 中,类的成员函数(包括静态和非静态成员函数)不占用类对象的内存空间,因为同一个类的所有对象共享同一份成员函数代码,成员函数代码通常存储在程序的代码区中,而不是存储在每个类对象的内部。
1 |
|
带静态成员变量的对象
C++ 中,类的静态成员变量不占用类对象的内存空间,因为静态成员变量由该类的所有对象共享,单独存储于程序的静态存储区,而不是存储在每个类对象内部。
1 |
|
带非静态成员变量的对象
C++ 中,类的非静态成员变量占用类对象的内存空间,因为每个对象都有自己独立的非静态成员变量副本,用于存储对象各自的状态。
1 |
|
