C++类成员在内存中的存储及对齐方式

C++类与对象内存布局
本文探讨了C++中类的内存布局细节,包括空类的大小、成员函数的存储方式、派生类与基类的关系、虚表机制、数据成员的排列规则等,并解释了static数据成员的特点。

一、空类的大小

  C++中空类的大小是1,这是因为空类也可以被实例化,为了确保每一个实例在内存中都有一个独一无二的地址,编译器往往隐含给一个空类加一个字节。

二、类中的成员函数与非虚成员函数

  类中的非虚成员函数不占用空间,虚函数表占用四个字节,只要有虚函数(无论有几个)都只占用四个字节。成员函数还是以一般的函数一样的存在。a.fun()是通过fun(a.this)来调用的。所谓成员函数只是在名义上是类里的。其实成员函数的大小不在类的对象里面,同一个类的多个对象共享函数代码。而我们访问类的成员函数是通过类里面的一个指针实现,而这个指针指向的是一个table,table里面记录的各个成员函数的地址(当然不同的编译可能略有不同的实现)。所以我们访问成员函数是间接获得地址的。所以这样也就增加了一定的时间开销,这也就是为什么我们提倡把一些简短的,调用频率高的函数声明为inline形式(内联函数)。

三、派生类与基类

  派生类继承基类的所有成员(包括私有数据成员),派生类的大小是在基类的大小的基础上再增加自己数据成员的空间。

四、虚表与类数据成员

  虚函数表首先存入内存中,然后是数据成员。

五、类的与结构体

  类的对齐规则与结构体基本一致,即取数据成员本身的对其数与编译器默认对齐数之间取小的那个数作为实际对齐数。

六、类的数据成员

  类的数据成员按其声明顺序加入内存,(与其访问权限无关,即无论public,private,protected的数据成员,只看其声明顺序)

七、static 数据成员不占用类的空间,对其派生类亦是如此。

### C++ 中类的成员函数、成员变量以及静态成员的内存布局 #### 成员变量存储方式 对于普通成员变量而言,这些变量被存储在对象自身的内存区域内。其内存布局遵循与 `struct` 变量相似的原则,并且会按照编译器规定的字节对齐方式进行排列[^1]。 ```cpp class Example { public: int a; // 按照默认字节对齐规则分配空间 char b; }; ``` 而静态成员变量则不同,它们并不属于任何一个特定的对象实例;相反,这类变量会被放置到程序的全局数据区中,在整个应用程序生命周期内保持存在[^2]。 #### 成员函数的存储位置 成员函数本身并不是作为对象的一部分存在于堆栈或自由存储区内,而是位于可执行文件的代码段之中。这意味着无论创建多少个该类型的对象,所有这些对象共享同一份成员函数副本[^3]。 ```cpp class MyClass { public: void myFunction() { /* 函数体 */ } // 此处定义的方法实际存放在代码段里 }; ``` 当调用某个对象上的成员方法时,实际上是通过传递隐式的 this 参数指向具体哪个实例来进行操作。 #### 静态成员的特点 无论是静态成员变量还是静态成员函数,两者均不依赖具体的对象实例即可访问。其中: - **静态成员变量**:如同其他全局变量一样保存在全球数据区; - **静态成员函数**:同样驻留在代码段,但由于没有this指针关联任何特定对象,因此无法直接修改非静态的数据成员[^4]。 综上所述,C++ 类型系统的这种设计使得可以在不影响性能的情况下实现面向对象编程的核心特性——封装性和多态性的同时也优化了资源利用率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值