c++类 | 类的大小
github热门推荐 › c++类 | 类的大小 (第 76 章)
一、核心原则
类的大小 = 非静态成员变量 按照内存对齐规则排列后的大小 + 虚函数表指针(如果有虚函数)+ 虚基类指针(如果有虚继承)
不影响类大小的因素:
-
✅ 成员函数(普通、静态、虚函数本身)
-
✅ 静态成员变量
-
✅ 静态常量成员变量
二、内存对齐规则(64位编译器)
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
对齐三原则:
-
每个成员的偏移量是该成员大小的整数倍
-
结构体总大小是最大成员大小的整数倍
-
成员按声明顺序排列
三、图形化讲解
┌─────────────────────────────────────────────────────────┐│ 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() 地址 │ ││ └──────────────┘ ││ │└─────────────────────────────────────────────────────────┘
四、完整代码示例
<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 字节
六、关键总结
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
七、快速记忆口诀
⚠️ 版权声明
本文为免费文章,欢迎转载。转载请注明出处:一木科技(https://www.pingquan.vip/2026/05/31/c%e7%b1%bb-%e7%b1%bb%e7%9a%84%e5%a4%a7%e5%b0%8f/),并保留原文链接。
还没有评论,来说两句?