c++类 | 类的大小

github热门推荐 › c++类 | 类的大小 (第 76 章)
文章工具

一、核心原则

类的大小 = 非静态成员变量 按照内存对齐规则排列后的大小 + 虚函数表指针(如果有虚函数)+ 虚基类指针(如果有虚继承)

不影响类大小的因素:

  • ✅ 成员函数(普通、静态、虚函数本身)

  • ✅ 静态成员变量

  • ✅ 静态常量成员变量


二、内存对齐规则(64位编译器)

类型
大小
对齐要求
char
1
1
short
2
2
int
4
4
float
4
4
double
8
8
指针
8
8
long long
8
8

对齐三原则:

  1. 每个成员的偏移量是该成员大小的整数倍

  2. 结构体总大小是最大成员大小的整数倍

  3. 成员按声明顺序排列


三、图形化讲解

┌─────────────────────────────────────────────────────────┐│  Class A(无虚函数,无继承)                              │├─────────────────────────────────────────────────────────┤│                                                         ││  成员变量(按声明顺序):                                 ││                                                         ││  偏移0:  const int c_var    ────┐                       ││  偏移4:  int var               ├─ 4+4=8字节             ││  偏移8:  char var1            ──┘                       ││  偏移9:  [PADDING 3字节]      ← 对齐到4的倍数            ││                                                         ││  总大小 = 12 字节                                        ││                                                         │└─────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────┐│  Class A(有虚函数)                                     │├─────────────────────────────────────────────────────────┤│                                                         ││  偏移0:  vptr (虚函数表指针)  ← 8字节                   ││  偏移8:  const int c_var      ← 4字节                  ││  偏移12: int var              ← 4字节                  ││  偏移16: char var1            ← 1字节                  ││  偏移17: [PADDING 7字节]      ← 对齐到8的倍数           ││                                                         ││  总大小 = 24 字节                                        ││                                                         ││  虚函数表(独立于对象):                                 ││  ┌──────────────┐                                       ││  │  f() 地址    │                                       ││  │  g() 地址    │                                       ││  │  h() 地址    │                                       ││  └──────────────┘                                       ││                                                         │└─────────────────────────────────────────────────────────┘

四、完整代码示例

C++ 片段需补全 main() 函数才能运行在实训台打开 →
<span leaf=""><span class="code-snippet__comment">// 文件:class_size_demo.cpp</span></span></code><code><span leaf=""><span class="code-snippet__comment">// 64位编译器下测试</span></span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">include</span></span><span class="code-snippet__meta"> </span><span class="code-snippet__meta"><span class="code-snippet__string"><iostream></span></span></span></code><code><span leaf=""><span class="code-snippet__keyword">using</span> <span class="code-snippet__keyword">namespace</span> std;</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 情况1:空类 ====================</span></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">Empty</span> {};</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 情况2:只有成员函数 ====================</span></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">OnlyFunction</span> {</span></code><code><span leaf=""><span class="code-snippet__keyword">public</span>:</span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">func1</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}</span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">func2</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}</span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__type">static</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">staticFunc</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}</span></code><code><span leaf="">};</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 情况3:只有静态成员 ====================</span></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">OnlyStatic</span> {</span></code><code><span leaf=""><span class="code-snippet__keyword">private</span>:</span></code><code><span leaf="">    <span class="code-snippet__type">static</span> <span class="code-snippet__type">int</span> s_var;</span></code><code><span leaf="">    <span class="code-snippet__type">static</span> <span class="code-snippet__type">const</span> <span class="code-snippet__type">int</span> SC_VAR = <span class="code-snippet__number">100</span>;</span></code><code><span leaf="">};</span></code><code><span leaf=""><span class="code-snippet__type">int</span> OnlyStatic::s_var = <span class="code-snippet__number">0</span>;</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 情况4:普通成员变量 ====================</span></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">NormalMembers</span> {</span></code><code><span leaf=""><span class="code-snippet__keyword">private</span>:</span></code><code><span leaf="">    <span class="code-snippet__type">char</span> c;     <span class="code-snippet__comment">// 1字节,偏移0</span></span></code><code><span leaf="">    <span class="code-snippet__type">int</span> i;      <span class="code-snippet__comment">// 4字节,偏移4(1+填充3)</span></span></code><code><span leaf="">    <span class="code-snippet__type">double</span> d;   <span class="code-snippet__comment">// 8字节,偏移8</span></span></code><code><span leaf="">    <span class="code-snippet__comment">// 总大小:偏移16,最大对齐8,16是8的倍数 → 16字节</span></span></code><code><span leaf="">};</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 情况5:顺序影响大小 ====================</span></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">BadOrder</span> {</span></code><code><span leaf=""><span class="code-snippet__keyword">private</span>:</span></code><code><span leaf="">    <span class="code-snippet__type">char</span> c;     <span class="code-snippet__comment">// 1字节,偏移0</span></span></code><code><span leaf="">    <span class="code-snippet__type">double</span> d;   <span class="code-snippet__comment">// 8字节,偏移8(1+填充7)</span></span></code><code><span leaf="">    <span class="code-snippet__type">int</span> i;      <span class="code-snippet__comment">// 4字节,偏移16</span></span></code><code><span leaf="">    <span class="code-snippet__comment">// 总大小:偏移20,对齐到8 → 24字节</span></span></code><code><span leaf="">};</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">GoodOrder</span> {</span></code><code><span leaf=""><span class="code-snippet__keyword">private</span>:</span></code><code><span leaf="">    <span class="code-snippet__type">double</span> d;   <span class="code-snippet__comment">// 8字节,偏移0</span></span></code><code><span leaf="">    <span class="code-snippet__type">int</span> i;      <span class="code-snippet__comment">// 4字节,偏移8</span></span></code><code><span leaf="">    <span class="code-snippet__type">char</span> c;     <span class="code-snippet__comment">// 1字节,偏移12</span></span></code><code><span leaf="">    <span class="code-snippet__comment">// 总大小:偏移13,对齐到8 → 16字节</span></span></code><code><span leaf="">};</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 情况6:带虚函数 ====================</span></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">WithVirtual</span> {</span></code><code><span leaf=""><span class="code-snippet__keyword">private</span>:</span></code><code><span leaf="">    <span class="code-snippet__type">int</span> a;      <span class="code-snippet__comment">// 4字节</span></span></code><code><span leaf="">    <span class="code-snippet__type">char</span> b;     <span class="code-snippet__comment">// 1字节</span></span></code><code><span leaf=""><span class="code-snippet__keyword">public</span>:</span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__keyword">virtual</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">vf1</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}</span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__keyword">virtual</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">vf2</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}</span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__keyword">virtual</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">vf3</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}</span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__keyword">virtual</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">vf4</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}   <span class="code-snippet__comment">// 多个虚函数不影响大小</span></span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">normalFunc</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}    <span class="code-snippet__comment">// 普通函数不影响</span></span></code><code><span leaf="">};</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 情况7:虚继承 ====================</span></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">Base</span> {</span></code><code><span leaf="">    <span class="code-snippet__type">int</span> x;</span></code><code><span leaf="">};</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">DerivedVirtual</span> : <span class="code-snippet__keyword">virtual</span> <span class="code-snippet__keyword">public</span> Base {</span></code><code><span leaf="">    <span class="code-snippet__type">int</span> y;</span></code><code><span leaf="">};</span></code><code><span leaf=""><span class="code-snippet__comment">// 虚继承会添加虚基类指针(vbptr),8字节</span></span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 情况8:完整示例 ====================</span></span></code><code><span leaf=""><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">CompleteExample</span> {</span></code><code><span leaf=""><span class="code-snippet__keyword">private</span>:</span></code><code><span leaf="">    <span class="code-snippet__type">static</span> <span class="code-snippet__type">int</span> s_var;           <span class="code-snippet__comment">// 不影响大小</span></span></code><code><span leaf="">    <span class="code-snippet__type">const</span> <span class="code-snippet__type">int</span> c_var;            <span class="code-snippet__comment">// 4字节</span></span></code><code><span leaf="">    <span class="code-snippet__type">int</span> var;                    <span class="code-snippet__comment">// 4字节 → 至此8字节</span></span></code><code><span leaf="">    <span class="code-snippet__type">char</span> var1;                  <span class="code-snippet__comment">// 1字节 → 9字节,填充到12</span></span></code><code><span leaf=""><span class="code-snippet__keyword">public</span>:</span></code><code><span leaf="">    <span class="code-snippet__built_in">CompleteExample</span>(<span class="code-snippet__type">int</span> temp) : <span class="code-snippet__built_in">c_var</span>(temp) {}</span></code><code><span leaf="">    ~<span class="code-snippet__built_in">CompleteExample</span>() {}</span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__keyword">virtual</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">f</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}         <span class="code-snippet__comment">// 添加vptr:8字节</span></span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__keyword">virtual</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">g</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}         <span class="code-snippet__comment">// 不影响大小</span></span></code><code><span leaf="">    <span class="code-snippet__function"><span class="code-snippet__keyword">virtual</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">h</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{}         <span class="code-snippet__comment">// 不影响大小</span></span></code><code><span leaf="">    <span class="code-snippet__comment">// 最终:12 + 填充(4) + 8 = 24字节</span></span></code><code><span leaf="">};</span></code><code><span leaf=""><br  /></span></code><code><span leaf=""><span class="code-snippet__comment">// ==================== 主函数测试 ====================</span></span></code><code><span leaf=""><span class="code-snippet__function"><span class="code-snippet__type">int</span></span><span class="code-snippet__function"> </span><span class="code-snippet__function"><span class="code-snippet__title">main</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span><span class="code-snippet__function"> </span>{</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"========== 基本情况 =========="</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(Empty):          "</span> << <span class="code-snippet__built_in">sizeof</span>(Empty) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(OnlyFunction):   "</span> << <span class="code-snippet__built_in">sizeof</span>(OnlyFunction) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(OnlyStatic):     "</span> << <span class="code-snippet__built_in">sizeof</span>(OnlyStatic) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf=""><br  /></span></code><code><span leaf="">    cout << <span class="code-snippet__string">"n========== 普通成员变量 =========="</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(NormalMembers):  "</span> << <span class="code-snippet__built_in">sizeof</span>(NormalMembers) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(BadOrder):       "</span> << <span class="code-snippet__built_in">sizeof</span>(BadOrder) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(GoodOrder):      "</span> << <span class="code-snippet__built_in">sizeof</span>(GoodOrder) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"(优化顺序可以节省空间!)"</span> << endl;</span></code><code><span leaf=""><br  /></span></code><code><span leaf="">    cout << <span class="code-snippet__string">"n========== 虚函数影响 =========="</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(WithVirtual):    "</span> << <span class="code-snippet__built_in">sizeof</span>(WithVirtual) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(CompleteExample):"</span> << <span class="code-snippet__built_in">sizeof</span>(CompleteExample) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf=""><br  /></span></code><code><span leaf="">    cout << <span class="code-snippet__string">"n========== 指针大小 =========="</span> << endl;</span></code><code><span leaf="">    WithVirtual* p;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(指针):           "</span> << <span class="code-snippet__built_in">sizeof</span>(p) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf=""><br  /></span></code><code><span leaf="">    <span class="code-snippet__comment">// 实例化对象</span></span></code><code><span leaf="">    <span class="code-snippet__function">CompleteExample </span><span class="code-snippet__function"><span class="code-snippet__title">ex</span></span><span class="code-snippet__function"><span class="code-snippet__params">(</span></span><span class="code-snippet__function"><span class="code-snippet__params"><span class="code-snippet__number">4</span></span></span><span class="code-snippet__function"><span class="code-snippet__params">)</span></span>;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"n========== 对象大小 =========="</span> << endl;</span></code><code><span leaf="">    cout << <span class="code-snippet__string">"sizeof(ex):             "</span> << <span class="code-snippet__built_in">sizeof</span>(ex) << <span class="code-snippet__string">" 字节"</span> << endl;</span></code><code><span leaf=""><br  /></span></code><code><span leaf="">    <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">0</span>;</span></code><code><span leaf="">}</span>

五、预期输出(64位编译器)

========== 基本情况 ==========sizeof(Empty):          1 字节      ← 空类特殊处理sizeof(OnlyFunction):   1 字节      ← 成员函数不影响sizeof(OnlyStatic):     1 字节      ← 静态成员不影响
========== 普通成员变量 ==========sizeof(NormalMembers):  16 字节sizeof(BadOrder):       24 字节sizeof(GoodOrder):      16 字节(优化顺序可以节省空间!)
========== 虚函数影响 ==========sizeof(WithVirtual):    16 字节     ← 8(vptr) + 4(int) + 1(char) + 3(填充) = 16sizeof(CompleteExample):24 字节
========== 指针大小 ==========sizeof(指针):           8 字节
========== 对象大小 ==========sizeof(ex):             24 字节

六、关键总结

场景
大小(64位)
说明
空类
1
保证不同对象有不同地址
只有函数
1
函数不占用对象空间
只有静态成员
1
静态成员共享,不属对象
普通成员变量
成员总和对齐后大小
遵循结构体对齐
有虚函数
上述 + 8
添加虚函数表指针(vptr)
虚继承
上述 + 8
添加虚基类指针(vbptr)
多虚函数
同上
所有虚函数共用一个vptr
场景
大小(64位)
说明
空类
1
保证不同对象有不同地址
只有函数
1
函数不占用对象空间
只有静态成员
1
静态成员共享,不属对象
普通成员变量
成员总和对齐后大小
遵循结构体对齐
有虚函数
上述 + 8
添加虚函数表指针(vptr)
虚继承
上述 + 8
添加虚基类指针(vbptr)
多虚函数
同上
所有虚函数共用一个vptr

七、快速记忆口诀

⚠️ 版权声明

本文为免费文章,欢迎转载。转载请注明出处:一木科技(https://www.pingquan.vip/2026/05/31/c%e7%b1%bb-%e7%b1%bb%e7%9a%84%e5%a4%a7%e5%b0%8f/),并保留原文链接。