C++类的大小(转)
一个空类class A{};的大小为什么是1,因为如果不是1,当定义这个类的对象数组时候A objects[5]; objects[0]和objects[1]就在同一个地址处,就无法区分。
单继承
#include<iostream>
using namespace std;
class A
{
public:
virtual void aa(){}
private:
char k[];
}; class B: public A
{
public:
virtual void bb(){}
}; int main()
{
cout<<"A's size is "<<sizeof(A)<<endl;
cout<<"B's size is "<<sizeof(B)<<endl;
return ;
}
vs和gcc下
执行结果:A's size is 8
B's size is 8
说明:有虚函数的类有个virtual table(虚函数表),里面包含了类的所有虚函数,类中有个virtual table pointers,通常成为vptr指向这个virtual table,占用4个字节的大小。成员类B public继承于A,类B的虚函数表里实际上有两个虚函数A::aa()和B::bb(),类B的大小等于char k[3]的大小加上一个指向虚函数表指针vptr的大小,考虑内存对齐为8。
#include<iostream>
using namespace std;
class A
{
public:
virtual void aa(){}
private:
char k[];
}; class B: public A
{
public:
//virtual void bb(){}
}; int main()
{
cout<<"A's size is "<<sizeof(A)<<endl;
cout<<"B's size is "<<sizeof(B)<<endl;
return ;
}
vs和gcc下
执行结果:A's size is 8
B's size is 8
说明:类B看上去没有虚函数,但实际上它有,只是没有重写,因为public继承,所以有从A继承过来的虚函数A::aa(),实际上类A和类B的虚函数表里的函数都是A::aa()。
#include<iostream>
using namespace std;
class A
{
public:
virtual void aa(){}
virtual void aa2(){}
private:
char k[];
}; class B: public A
{
public:
virtual void bb(){}
virtual void bb2(){}
}; int main()
{
cout<<"A's size is "<<sizeof(A)<<endl;
cout<<"B's size is "<<sizeof(B)<<endl;
return ;
}
vs和gcc下
执行结果:A's size is 8
B's size is 8
说明:一个类里若有虚函数,无论有多少个虚函数都只有一个指向虚表的指针,虚表中的每一个表项保存着一个虚函数的入口地址。当调用虚函数时,先找到虚表中它对应的表项,找到入口地址再执行。对于直接单继承,无论类B中有无虚函数,由于它继承了类A,且类A里含有虚函数,因此如果类B有虚函数,那么它和类A的是在同一个属于类B的虚表里,这张虚表的虚函数为A::aa()、A::aa2()、B::bb()、B::bb2()。注意:类A里的私有成员在类B里仍占有内存。
多继承
#include<iostream>
using namespace std;
class A
{
public:
virtual void aa(){}
virtual void aa2(){}
private:
char k[];
}; class B
{
public:
virtual void bb(){}
virtual void bb2(){}
}; class C: public A,public B
{
public:
virtual void aa(){} //重写了A的aa()
virtual void cc(){}
}; int main()
{
cout<<"A's size is "<<sizeof(A)<<endl;
cout<<"B's size is "<<sizeof(B)<<endl;
cout<<"C's size is "<<sizeof(C)<<endl;
return ;
}
vs和gcc下
执行结果:A's size is 8
B's size is 4
B's size is 12
说明:类A和B的大小就不解释了,参照上面。类C多重继承于A和B(有虚函数覆盖),那么类C的大小是多少?先看成员变量,有一个继承A的char k[3]。再看虚函数,类C的中虚函数是怎么分布的?先有一个虚函数表,里面有继承于类A的虚函数和C自己的虚函数(C::aa(), A::aa2(), C::cc()),如果C没有重写aa(),那么第一个虚函数就是A::aa(),接着有第二张虚函数表是继承包含类B的虚函数B::bb()、B::bb2()(类C没有重写B的虚函数)。总的大小就是2张虚表的大小(也即两个虚函数指针的大小)8字节加上3字节的k[3],考虑内存对齐,就是12字节。
虚继承
#include<iostream>
using namespace std;
class A
{
public:
virtual void aa(){}
private:
char k[];
}; class B: virtual public A
{
public:
//virtual void bb(){}
}; int main()
{
cout<<"A's size is "<<sizeof(A)<<endl;
cout<<"B's size is "<<sizeof(B)<<endl;
return ;
}
vs和gcc下
执行结果:A's size is 8
B's size is 12
说明:类B里包含,继承的char k[3],继承的虚函数,类B的虚函数表里有A::aa(),因为是虚继承,还有一个指向父类的指针,该指针为指向虚基类的指针(Pointer to virtual base class)。考虑内存对齐,总大小为12。
#include<iostream>
using namespace std;
class A
{
public:
virtual void aa(){}
private:
char k[];
}; class B: public virtual A
{
public:
virtual void bb(){}
}; int main()
{
cout<<"A's size is "<<sizeof(A)<<endl;
cout<<"B's size is "<<sizeof(B)<<endl;
return ;
}
VS执行结果:A's size is 8
B's size is 16
gcc执行结果:A's size is 8
B's size is 12
说明:对于虚继承,类B虚继承类A时,首先要通过加入一个指针来指向父类A,该指针被称为虚基类指针。然后包含从父类继承过来的3个char,再加上一个虚函数指针。考虑内存对齐,在gcc下结果是4+4+4=12。在VS下,结果是16,why?这一题和上一题区别只是在类B中添加了一个虚函数,但是两个题目中类B都有虚函数表。在VS下调试查看汇编代码,发现多出来的4字节什么也没有。
转自:http://www.cnblogs.com/luxiaoxun/archive/2012/09/01/2666395.html
C++类的大小(转)的更多相关文章
- 类的大小——sizeof 的研究
类的大小——sizeof 的研究(1) 先看一个空的类占多少空间? class Base { public: Base(); ~Base(); }; 注意到我这里显示声明了构造跟析构,但是sizeof ...
- c++空类的大小
初学者在学习面向对象的程序设计语言时,或多或少的都些疑问,我们写的代码与最终生编译成的代码却大相径庭,我们并不知道编译器在后台做了什么工作.这些都是由于我们仅停留在语言层的原因,所谓语言层就是教会我们 ...
- C++空类以及没有成员变量的类的大小
关于C++中空类的大小为1,我们大家都有所了解,但是除了空类之外的其他一些没有成员变量的类的大小,还是有很多不明之处的. 我们来看如下一个例子: #include<iostream> us ...
- C++类的大小
C++类的大小 一个空类class A{};的大小为什么是1,因为如果不是1,当定义这个类的对象数组时候A objects[5]; objects[0]和objects[1]就在同一个地址处,就无 ...
- 关于虚拟继承类的大小问题探索,VC++ 和 G++ 结果是有区别的
昨天笔试遇到个 关于类占用的空间大小的问题,以前没怎么重视,回来做个试验,还真发现了问题,以后各位笔试考官门,出题时请注明是用什么编译器. vc6/vc8 cl 和 Dev-C 的g++ 来做的测试: ...
- C++类对象大小的计算
(一)常规类大小计算 C++类对象计算需要考虑很多东西,如成员变量大小,内存对齐,是否有虚函数,是否有虚继承等.接下来,我将对此举例说明. 以下内存测试环境为Win7+VS2012,操作系统为32位 ...
- sizeof求类的大小
用sizeof求类的大小,http://blog.csdn.net/szchtx/article/details/10254007(sizeof浅析(三)——求类的大小),这篇博文给出了非常详尽的举例 ...
- C++类的大小计算汇总
C++中类涉及到虚函数成员.静态成员.虚继承.多继承.空类等. 类,作为一种类型定义,是没有大小可言的. 类的大小,指的是类的对象所占的大小.因此,用sizeof对一个类型名操作,得到的是具有该类型实 ...
- C++类的大小——sizeof(class)
第一:空类的大小 class CBase { }; 运行cout<<"sizeof(CBase)="<<sizeof(CBase)<<endl; ...
- C++学习笔记(8)----C++类的大小
C++类的大小 (i) 如下代码: #include<iostream> using namespace std; class CBase { }; class CDerive :publ ...
随机推荐
- 02 Java 的基本类型
Java 的基本类型 Java 包括了八种基本类型,明细如下: Java 的基本类型都有对应的值域和默认值.byte,short,int,long,float以及double的值域依次扩大,前面的值域 ...
- pat 1037
如果你是哈利·波特迷,你会知道魔法世界有它自己的货币系统 —— 就如海格告诉哈利的:“十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一个西可,很容易.”现在,给定 ...
- 设计模式(Java随笔)—装饰模式
装饰模式(Decorator Pattern):为已有功能动态地添加更多功能的一种方式Attach additional responsiblities to an object dynamicall ...
- 刷题总结——树的同构(bzoj4337 树上hash)
Description 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如 ...
- 如何用1个小时了解JSON
W3school ↑↑↑学这个,1个小时够了.下面是节选: 代码例子1: <html> <body> <h2>在 JavaScript 中创建 JSON 对象< ...
- Python Base Three
//sixth day to study python(2016/8/7) 32. In python , there are have an special type dictionary , it ...
- Python Base Two
//fourth day to study python 24. In python , how to create funcation. we can use def to define funca ...
- [转] Makefile 基础 (7) —— Makefile 中 make 的运行
该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...
- PHP的图片处理类(缩放、加图片水印和剪裁)
<!--test.php文件内容--> <?php //包含这个类image.class.php include "image.class.php"; $img ...
- bzoj 3456 城市规划 无向简单连通图个数 多项式求逆
题目大意 求n个点的无向简单连通图个数 做法1 \(f[i]\)表示i个点的无向简单连通图个数 \(g[i]=2^{\frac {i*(i-1)}{2}}\)表示i个点的无向简单图个数(不要求连通) ...