%% # 纲要 > 主干纲要、Hint/线索/路标 # Q&A #### 已明确 #### 待明确 > 当下仍存有的疑惑 **❓<font color="#c0504d"> 有什么问题?</font>** # Buffer ## 闪念 > sudden idea ## 候选资料 > Read it later %% # C++中的对象模型(对象的内存模型) > **对象** (`class object`),也称 "**类的实例对象**" ![[_attachment/02-开发笔记/01-cpp/类与对象/cpp-对象模型.assets/IMG-cpp-对象模型-7D6E33ED478AF842BAA1D3C53819E6D9.png|662]] <br><br> # 类成员实例 - **类**导出的部分:(**仅一份实体**,所有类的实例成员共享) - **静态数据成员** - **非内联成员函数** - **==虚函数表==**(virtual table,vtbl) - **类实例对象**包含的部分:(每个实例对象持有一份独立实体) - **非静态数据成员** - **==虚函数指针==**(vptr) => 指向 "**类的虚函数表**"; --- > [!NOTE] 虚函数表指针的设置和重置由类的构造函数、析构函数和拷贝赋值运算符自动完成。 %% ###### Deprecated - 每个==**类实例对象**==独立持有一份 **"非静态数据成员" 的实体**。 - **类的==静态数据成员==只存在一个实体**,被所有类实例对象共享。 - 类的**所有==非内联成员函数==(静态、非静态成员函数)都只存在一个实体**。 - 关于虚函数: - **每个 class(而非 object)持有一张==虚函数表**==(virtual table, **vtbl**), - 表中存放着**指向其各个虚函数**的==**指针**==。 - 每个 class 所关联的 `type_info` 对象(用以支持 RTTI)也经由 virtual table 被指出来,通常置于表格的第一个 slot; - **每个类实例对象中持有一个==指针**== **vptr**,指向==**类的虚函数表**==。 %% <br><br> # 对象的内存大小 C++中一个类的实例对象所占内存大小**由以下三点决定** [^1]: - (1)**所有==非静态==成员变量的总大小**(包括 **==继承==** 而来的**基类的非静态数据成员**) - (2)**字节对齐**(为满足对齐要求,**编译器可能会在成员变量之间插入填充字节**(padding)) - (3)**==虚指针==**(指向对象所属类的虚函数表的指针 `vptr`) - 如果一个类**有虚函数**,**编译器会为每个对象添加一个指向虚函数表的指针**。 > [!info] **空类(empty class)** 的实例对象至少==占 1 字节大小==,而不是不占内存空间。 > > 虽然空类没有任何数据成员,但编译器会为每个空类的对象 **分配至少一个字节的空间,以==确保不同的对象有不同的地址==**。 > 如果不占内存,那么空类就无法实例化。 > [!example] 示例 > > ```cpp > class MyClass { > int a; // 4字节(取决于平台) > char b; // 1字节 > static int c; // 静态数据成员不计入实例对象的大小. > }; > > class Derived : public MyClass { > double d; // 8字节(取决于平台) > }; > ``` > > 在大多数 64 位平台上,`MyClass` 的大小应当是 8 字节(char 后补 3),而 `Derived` 的大小应当是 16 字节。 <br><br> # 参考资料 # Footnotes [^1]: 《深度探索 C++对象模型》P27