当前位置: 首页 > news >正文

面向对象编程基础:类的实例化与对象内存模型详解

目录

一、类的实例化详解

1、什么是类的实例化?

2、关键概念

类如同模型或蓝图

实例化创建实际对象

现实类比

2、代码示例

示例说明

3、重要结论(重要!!!)

二、类对象模型与内存布局详解

1、类对象的内存结构(重要!!!)

成员变量存储

成员函数存储

存储效率考量

2、类对象存储模型图示

3、类大小计算规则

基本规则

特殊类大小说明

4、验证示例

类Person的对象内存布局:

5、结构体内存对齐规则详解

基本规则

VS编译器默认值

嵌套结构体规则

对齐示例

6、重要结论


一、类的实例化详解

1、什么是类的实例化?

  • 类实例化是指用类类型在物理内存中创建对象的过程

  • 类是对对象的一种抽象描述,是一种模型或蓝图

  • 类限定了成员变量和成员函数,但这些只是声明,不会分配实际内存空间

2、关键概念

类如同模型或蓝图

  • 类定义仅规定了类包含哪些成员(属性和方法)

  • 定义类时并不会分配实际的内存空间

  • 类似于C语言中定义结构体类型但不创建变量

实例化创建实际对象

  • 一个类可以实例化出多个对象,每个对象都是独立的实体,互不干扰

  • 只有在实例化对象时,系统才会为成员变量分配实际的物理内存空间

  • 每个对象占用独立的物理内存空间存储其成员变量

  • 类似于用结构体类型创建变量时分配实际内存

现实类比

类实例化对象就像使用建筑设计图建造房子:

  • 相当于设计图:规划了房间数量、大小和功能,图纸本身(类)没有实体存在

  • 实例化就是根据图纸建造实际的房子

  • 对象相当于实际建造的房子,只有建造出的房子(对象)才占用物理空间:可以实际使用和居住

  • 设计图(类)本身不能住人,只有建好的房子(对象)才能住人

2、代码示例

#include<iostream>
using namespace std;class Date {
public:// 初始化日期void Init(int year, int month, int day) {_year = year;_month = month;_day = day;}// 打印日期void Print() {cout << _year << "/" << _month << "/" << _day << endl;}private:// 这里只是声明成员变量,没有实际分配空间int _year;int _month;int _day;
};int main() {// Date类实例化出对象d1和d2Date d1;  // 第一个Date对象Date d2;  // 第二个Date对象// 初始化并打印d1d1.Init(2024, 3, 31);d1.Print();// 初始化并打印d2d2.Init(2024, 7, 5);d2.Print();return 0;
}

示例说明

  1. 类定义阶段

    • Date类定义了三个私有成员变量(_year_month_day

    • 此时只是声明,没有分配内存空间

  2. 实例化阶段

    • Date d1Date d2语句实际创建了两个Date对象

    • 此时系统为每个对象分配独立的内存空间来存储其成员变量

  3. 对象使用

    • 每个对象可以独立调用成员函数(Init()Print()

    • 对象之间的数据互不干扰(d1和d2存储不同的日期值)

3、重要结论(重要!!!)

  • 类定义只是描述了对象的结构和行为

  • 只有实例化后才会为对象分配内存,才能实际使用类的功能

  • 每个对象都有自己独立的成员变量存储空间,每个对象都有自己独立的状态(成员变量值)

  • 类的方法(成员函数)被所有对象共享,不占用对象的内存空间

  • 类是抽象的模板,对象是具体的实例

理解类的实例化是面向对象编程的基础,它体现了"抽象"与"具体"的关系。


二、类对象模型与内存布局详解

1、类对象的内存结构(重要!!!)

类对象在内存中的存储方式遵循以下原则:

成员变量存储

  • 每个对象独立存储自己的成员变量

  • 不同对象的成员变量值互不影响

  • 成员变量按照结构体内存对齐规则排列

成员函数存储

  • 所有对象共享同一份成员函数代码

  • 成员函数存储在公共代码区,不占用对象的内存空间

  • 成员函数编译后成为指令代码,存储在代码段(公共代码区)

  • 对象中不存储成员函数指针(避免重复存储浪费空间)

  • 函数调用地址在编译链接时确定,运行时直接通过固定地址调用

存储效率考量

  • 若存储函数指针,100个对象将重复存储100次相同指针

  • 实际只需在代码段保存一份函数实现,所有对象共享

2、类对象存储模型图示

3、类大小计算规则

基本规则

  • 类大小等于其所有非静态成员变量大小之和(考虑内存对齐)

  • 静态成员变量不占用类对象空间(存储在全局区)

  • 成员函数不占用类对象空间

特殊类大小说明

  1. 空类大小

    • 大小为1字节(编译器分配的占位标识,确保对象有唯一地址)

    • 示例:class C{}; → 1字节

  2. 仅有成员函数的类

    • 大小同样为1字节

    • 示例:class B{void Print(){}}; → 1字节

  3. 含成员变量的类

    • 大小为成员变量总和(考虑对齐)

    • 示例:class A{char _ch; int _i;}; → 8字节(1+3填充+4)

4、验证示例

#include <iostream>
using namespace std;class Person
{
public:void ShowInfo(){cout << _name << "-" << _sex << "-" << _age << endl;}public:char *_name; // 姓名 (指针类型,通常4/8字节)char *_sex;  // 性别 (指针类型,通常4/8字节)int _age;    // 年龄 (通常4字节)
};// 测试类
class A1
{
public:void f1() {}private:int _a;
};
class A2
{
public:void f2() {}
};
class A3
{
};int main()
{cout << "Person size: " << sizeof(Person) << endl; // 通常12/24字节(取决于指针大小)cout << "A1 size: " << sizeof(A1) << endl;         // 4 (int)cout << "A2 size: " << sizeof(A2) << endl;         // 1 (只有成员函数)cout << "A3 size: " << sizeof(A3) << endl;         // 1 (空类)return 0;
}

类Person的对象内存布局

5、结构体内存对齐规则详解

基本规则

  • 第一个成员变量位于偏移量0处
  • 后续成员对齐到min(成员大小, 编译器默认对齐数)的整数倍地址
  • 结构体总大小为最大对齐数的整数倍

VS编译器默认值

  • 默认对齐数为8字节
  • 实际对齐数取成员大小和默认对齐数的较小值

嵌套结构体规则

  • 嵌套结构体对齐到其自身最大对齐数的整数倍处
  • 整体大小是所有最大对齐数(含嵌套结构体)的整数倍

对齐示例

struct Example {char a;     // 1字节,偏移0// 3字节填充(因为int要对齐到4)int b;      // 4字节,偏移4short c;    // 2字节,偏移8// 2字节填充(总大小需为4的整数倍)
};              // 总大小:12字节

6、重要结论

  1. 对象只存储成员变量,成员函数存储在公共代码区(代码段)

  2. 类大小计算只考虑成员变量,需遵循内存对齐规则,可能包含填充字节

  3. 空类有1字节占位符,保证每个对象有唯一地址,仅有成员函数的类大小也为1字节(占位标识)

  4. 内存对齐能提高CPU访问效率,但可能增加空间开销(内存对齐牺牲部分空间换取CPU访问效率提升)

  5. 实际开发中应注意类成员排列顺序以优化内存使用

http://www.lryc.cn/news/610808.html

相关文章:

  • 什么是mysql的垂直分表,理论依据是什么,如何使用?
  • 单链表应用实践
  • 【PCIE044】基于 JFM7VX690T 的全国产化 FPGA 开发套件
  • FPGA 基本设计思想--乒乓操作、串并转换、流水线
  • 数学建模算法-day[15]
  • 【MATLAB】(八)矩阵
  • 技术与情感交织的一生 (十一)
  • HTTP 与 HTTPS 的区别深度解析:从原理到实践
  • kettle插件-kettle http post plus插件,轻松解决https post接口无法调用文件流下载问题
  • 攻击实验(ARP欺骗、MAC攻击、报文洪水攻击、DNS欺骗)
  • 在 MCP 中实现 “askhuman” 式交互:原理、实践与开源方案
  • 灰色优选模型及算法MATLAB代码
  • 信息安全概述--实验总结
  • TCP如何实现可靠传输?实现细节?
  • 三极管基本放大电路静态及动态参数计算
  • 原生CSS vs LESS:样式表语言的进化之旅
  • 笔记学习杂记
  • (ZipList入门笔记二)为何ZipList可以实现内存压缩,可以详细介绍一下吗
  • 第19章 枚举器和迭代器 笔记
  • Spring小细节
  • MySQL连接解决:“Host is not allowed to connect to this MySQL server”错误详解
  • HTML总结全览
  • 解决错误nvcc fatal : Unsupported gpu architecture ‘compute_86‘
  • ESOP-3D系统实现机械设备生产流程的可追溯性
  • 人工智能领域、图欧科技、IMYAI智能助手2025年5月更新月报
  • 树状数组的性质
  • AI 对话高效输入指令攻略(四):AI+Apache ECharts:生成各种专业图表
  • C++ ---》string类的模拟实现
  • Solidity智能合约基础
  • 单目云台双摄像头配置双摄像头的优势