写在前面的话(就先听听)
最近面试一直被面试官问道:
- 一个类有什么什么变量,静态变量等,请问这个类所占内存多少字节呢?
- 假如这个类含有若干个虚函数,然后还有子类又定义了一些的自定义成员和成员函数,还有虚函数之类的?那么子类占用多少字节呢?
- 然后子类又继承了一个孙子类,孙子类有添加了若干个成员,然后定义了什么函数虚函数之类的,请问孙子类的内存大小又是多少呢?
然后就一直摸棱两可的回答了一通,自己也没有弄清楚,什么大小啊,还有虚函数表怎么继承啊,怎么修改啊,被怼的很厉害,于是下决心自己好好整理一下,希望对大家也有帮助。
正文
首先,我们在计算这个类所占内存大小的时候,心里应该有6个宗旨,总结就是:(后面会有解释原因)
- 空类占用1个字--------------------------------------------------------1(详情见知乎)
- 静态成员变量不占内存大小----------------------------------------0
- 普通成员函数不占内存大小----------------------------------------0
- 只要含有虚函数(继承的或者是自定义)的占内存---------1个字(不是字节,是根据你机器位数变化的)
- 所有的非静态成员变量---------------------------------------------本身类定义的成员变量总和+父类继承下来的所有变量总和
- 注意字节对齐原则(整字数)
只要把这6个原则记住了,问题不大了。但是呢除了记住这几个大的原则呢,还要知道为什么最好。下面就一一对5个原则进行补充。
详细分析(配有参考链接):
- 为什么空类占用1个字:
答案就是因为https://blog.csdn.net/zhaoxd200808501/article/details/72845691(看看别人大牛写的)
简单来说就是系统为了标识一个类,不占用内存在什么地方记录这个类的存在呢,那么怎么记录呢,C/C++都是通过指针(一个字)来记录,所以就不为空。
- 2-3这两个记住就行了,静态变量已经不属于某个对象了,还有成员函数,可以将它们看作是“游离”的内存块即可。
- 第四条应该注意的是:
- 一个类中不管有多少个虚函数,虚函数表指针永远只有一个(只占一个字),这个指针是虚函数地址数组的首地址。数组元素是各个虚函数的地址,因此只需要知道这个首地址,那么就可以找到所有的虚函数。
- 子类继承父类的时候:
- 父类有虚函数,如果子类没有虚函数,那么计算子类内存大小的时候,子类继承了父类虚函数,他就含有了虚函数,他就要加上那个虚函数表的一个字的内存大小;
- 父类有虚函数,但是自己也定义的虚函数或者覆盖了父类的虚函数,这样子类也算是有了很多虚函数,虚函数表也是同样占用一个字的内存大小。
- 父类没有虚函数,子类含有虚函数:就在父类基础上加上一个字虚函数表的大小
- 父类和子类都没有那就什么都不用加了呀。
- 孙子类和儿子类也是按照父类和子类的方法相同。
- 第5条需要注意的一种情况是大家会有这样的疑问:假如父类的非静态成员变量是私有private的话,子类根本不继承啊,那么子类计算内存大小的时候还要加上这些父类私有变量吗?
答案是“加上”。即使没有权限不能使用这些变量,但是计算子类的内存大小的时候也要加上父类继承下来的成员变量大小。不够整个字数的凑够整个字数就可以了。
总结起来就是:
子类内存大小=父类内存大小+子类自定义的成员变量大小
详细的各种图案可以查看https://blog.csdn.net/changyang208/article/details/78668462 这位大佬写的很详细很详细。
希望不明白的或者写的有误的,大家可以留言多多指正和讨论。