【C++】类和对象--类对象模型与大小计算

目录

在上一篇中,我们理解了类的定义和封装。类是对象的模板,而对象是类的实例。那么,一个对象在内存中究竟长什么样?它占据多大空间?本文将剖析类对象的存储模型和大小计算规则。

类的实例化:从蓝图到建筑

类描述了实体具有哪些属性和方法,但它本身不占用实际的物理存储。只有当类被实例化------即定义出具体的对象时,程序才会在内存中开辟空间存放该对象的成员变量。

一个类可以实例化出多个对象,每个对象拥有独立的成员变量副本。正如建筑蓝图可以造出许多功能相同但地址不同的房子。

cpp 复制代码
class Stack {
    int* _array;
    size_t _capacity;
    size_t _top;
};
// 实例化两个对象,各占独立内存
Stack st1;
Stack st2;

对象大小的计算与存储模型

一个关键问题是:成员函数会占据对象空间吗? 答案是否定的。C++编译器会将类的成员函数存放在公共代码段(只读区域),所有对象共享同一份函数实现。对象本身只需要存储属于自己独有的数据,即成员变量。

因此,计算一个对象的大小时,只需要考虑其成员变量所占空间,并遵循与C语言结构体相同的内存对齐规则。

特殊情况:空类。如果一个类既没有成员变量也没有虚函数(虚函数会引入虚表指针),它的大小并不是0,而是1字节。这1字节不存储任何实际数据,仅为了在内存中唯一标识该对象,使不同对象的地址不同。

cpp 复制代码
class A1 {};       // sizeof(A1) == 1
class A2 {
public:
    A2() {}
};                  // sizeof(A2) == 1 (成员函数不占对象空间)

结构体内存对齐规则

对象大小并不是成员变量大小的简单累加,编译器会进行内存对齐以提高存取效率。主流平台默认对齐数通常为8(VS中即为8)。规则如下(与C语言struct完全一致):

  1. 第一个成员:放在与对象起始地址偏移量为0的位置。
  2. 其他成员:每个成员要对齐到某个地址,该地址必须是 对齐数 的整数倍
    对齐数 = min(编译器默认对齐数, 该成员自身大小)
  3. 整体大小:对象的总大小必须是最大对齐数的整数倍。
  4. 嵌套结构体:如果类中包含另一个类的对象作为成员,该成员对齐到自身内部最大对齐数的整数倍位置,整个类的大小也要考虑该子对象的最大对齐数。

示例分析:

cpp 复制代码
class Example {
    char c;    // 大小1,对齐数 min(8,1)=1,偏移0
    int  i;    // 大小4,对齐数 min(8,4)=4,下次对齐到偏移4,c后填充3字节
    short s;   // 大小2,对齐数 min(8,2)=2,当前偏移8,满足对齐,占2字节,总10
}; // 最大对齐数为4,总大小需为4的倍数,末尾填充2字节 => 12

掌握对象内存模型,是我们理解this指针传参、深浅拷贝以及继承多态的物理基础。下一篇将聚焦那个隐藏在幕后却至关重要的角色------this指针。

相关推荐
布朗克1682 小时前
Go 入门到精通-15-错误处理
开发语言·python·golang·错误处理
zzb15802 小时前
Zed 配置 Swift / iOS 开发
开发语言·ios·swift
北冥you鱼4 小时前
Go-Ethereum (Geth) 最佳实践:从部署到生产环境优化
开发语言·后端·golang
这不小天嘛10 小时前
JAVA八股——J集合篇
java·开发语言
AOwhisky11 小时前
Python 学习笔记(第一期与第二期)——基础语法——核心知识点自测与详解
开发语言·笔记·python·学习·云原生·运维开发
喜欢的名字被抢了13 小时前
Python实战:SQLAlchemy ORM与FastAPI项目集成
开发语言·python·sql·教程·fastapi
从零开始的代码生活_15 小时前
C++ 内存管理:从内存分区到 new/delete 底层原理
开发语言·c++·后端
wabs66616 小时前
关于单调栈【力扣739.每日温度的思考】
java·开发语言
AOwhisky16 小时前
Python 学习笔记(第三期)——流程控制核心知识点自测与详解
开发语言·笔记·python·学习·云原生·运维开发·流程控制