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 ...
随机推荐
- jsf taglib定义函数
创建文件 在文件中添加function标签 <function> <function-name>getFileContent</function-name> & ...
- webresource.axd文件的配置及使用
今天看到同事的代码中使用到了webresource.axd,特地认真地看了一下它的使用.主要用途有两点: 1.当作httphandler用,但是比handler更好用一点,不需要考虑路径,用的时候,只 ...
- Spring学习之代理
Spring的核心就是IOC和AOP IOC就是控制反转: 就是用配置文件的方式给javabean 赋值. 正常的在程序里;用new 的方式创建一个对象的时候,他就固定了值, 如果是注入的方式的话 ...
- sublime_2014-11-19
http://xionggang163.blog.163.com/blog/static/376538322013930104310297/ 直接输入注册码就可以了 ----- BEGIN LICEN ...
- System V 消息队列
3.1 概述 消息队列结构: struct msqid_ds { struct ipc_perm msg_perm; //权限结构 struct msg *msg_first; //队列中第一个消息 ...
- UIView-图层方法
// // ViewController.m // UIView-图层概念 // // Created by wangtouwang on 15/5/5. // Copyright (c) 2015年 ...
- 测试网站是共享还是独立ip
查看是共享还是独立:http://www.yougetsignal.com/tools/web-sites-on-web-server/ 站长工具:http://tool.webmasterhome. ...
- JS分段上传文件(File)并使用MD5.js加密文件段用来后台校验
HTML <form method="POST" name="form1" action="/mupload/upload/" enc ...
- java 文件类操作(转载)
11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...
- Leaflet学习笔记-基础内容
为什么选择Leaflet 开源,且代码仅有 31 KB,但它具有开发人员开发在线地图的大部分功能(80%的功能) 是不是比arcgis要小很多呢 官网:http://leafletjs.com/ 劣势 ...