C++类的大小
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[3];
};
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 0;
}

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[3];
};
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 0;
}

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[3];
};
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 0;
}

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[3];
};
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 0;
}

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[3];
};
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 0;
}

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[3];
};
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 0;
}

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字节什么也没有。
关于C++虚函数,可以看《C++虚函数表解析》:http://blog.csdn.net/haoel/article/details/1948051
C++类的大小的更多相关文章
- 类的大小——sizeof 的研究
类的大小——sizeof 的研究(1) 先看一个空的类占多少空间? class Base { public: Base(); ~Base(); }; 注意到我这里显示声明了构造跟析构,但是sizeof ...
- c++空类的大小
初学者在学习面向对象的程序设计语言时,或多或少的都些疑问,我们写的代码与最终生编译成的代码却大相径庭,我们并不知道编译器在后台做了什么工作.这些都是由于我们仅停留在语言层的原因,所谓语言层就是教会我们 ...
- C++空类以及没有成员变量的类的大小
关于C++中空类的大小为1,我们大家都有所了解,但是除了空类之外的其他一些没有成员变量的类的大小,还是有很多不明之处的. 我们来看如下一个例子: #include<iostream> us ...
- 关于虚拟继承类的大小问题探索,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 ...
随机推荐
- mysql数据库文件默认保存目录(windows)
如果没有自己去设置安装路径,MYSQL默认安装在C:/Program Files/MySQL/MySQL Server 5.1,新建的数据库文件在C:/Documents and Settings/A ...
- 如何理解systemstate
什么是systemstate一个systemstate是由在实例中调用生成systemstats时由每一个进程的进程状态组成.而每一个进程状态是由每一个进程所持有的当前对象所对应的详细对象状态信息组成 ...
- 讲解最好的Python正则表达式
这篇文章转载自:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html#!comments 这里非常感谢作者无私的贡献自己的成果. 请大 ...
- 九度OJ 1453 Greedy Tino -- 动态规划
题目地址:http://ac.jobdu.com/problem.php?pid=1453 题目描述: Tino wrote a long long story. BUT! in Chinese... ...
- 判断JS对象是否拥有某属性的方法举例
判断JS对象是否拥有某属性 JS是否拥有某属性的判断方法,这里提供两种方式,供大家参考. 1.in 运算符 var obj = {name:'jack'}; alert('name' in obj); ...
- html5异步上传图片显示上传文件进度条
<html> <head> </head> <body> <p> emo_album_id:<input type="tex ...
- js初学必知三重点
这里列出了一些JS重要知识点(不全面,但自己感觉很重要).彻底理解并掌握这些知识点,对于每个想要深入学习JS的朋友应该都是必须的. 讲解还是以示例代码搭配注释的形式,这里做个小目录: JS代码预解析原 ...
- js获取url的get传值函数
function getvl(name) { var reg = new RegExp("(^|\\?|&)"+ name +"=([^&]*)(\\s| ...
- C语言结构体中的函数指针
这篇文章简单的叙述一下函数指针在结构体中的应用,为后面的一系列文章打下基础 本文地址:http://www.cnblogs.com/archimedes/p/function-pointer-in ...
- 方便mac os 10.9系统中phpstorm配置php运行环境
自己安装php,不用mac安装,这样就有php开发环境了. 安装很简单,直接运行一个命令, 需要几分钟,请慢慢等待. curl -s http://php-osx.liip.ch/install.sh ...