%%
# 纲要
> 主干纲要、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