一个类的实例化对象所占空间的大小

注意不要说类的大小,是类的对象的大小.

首先,类的大小是什么?确切的说,类只是一个类型定义,它是没有大小可言的。 
用sizeof运算符对一个类型名操作,得到的是具有该类型实体的大小。 
如果 
Class A; 
A obj; 
那么sizeof(A)==sizeof(obj) 
那么sizeof(A)的大小和成员的大小总和是什么关系呢,很简单,一个对象的大小大于等于所有非静态成员大小的总和。 
为什么是大于等于而不是正好相等呢?超出的部分主要有以下两方面: 
1) C++对象模型本身 
对于具有虚函数的类型来说,需要有一个方法为它的实体提供类型信息(RTTI)和虚函数入口,常见的方法是建立一个虚函数入口表,这个表可为相同类型的对象共享,因此对象中需要有一个指向虚函数表的指针,此外,为了支持RTTI,许多编译器都把该类型信息放在虚函数表中。但是,是否必须采用这种实现方法,C++标准没有规定,但是这几户是主流编译器均采用的一种方案。 
2) 编译器优化 
因为对于大多数CPU来说,CPU字长的整数倍操作起来更快,因此对于这些成员加起来如果不够这个整数倍,有可能编译器会插入多余的内容凑足这个整数倍,此外,有时候相邻的成员之间也有可能因为这个目的被插入空白,这个叫做“补齐”(padding)。所以,C++标准紧紧规定成员的排列按照类定义的顺序,但是不要求在存储器中是紧密排列的。 
基于上述两点,可以说用sizeof对类名操作,得到的结果是该类的对象在存储器中所占据的字节大小,由于静态成员变量不在对象中存储,因此这个结果等于各非静态数据成员(不包括成员函数)的总和加上编译器额外增加的字节。后者依赖于不同的编译器实现,C++标准对此不做任何保证。

C++标准规定类的大小不为0,空类的大小为1,当类不包含虚函数和非静态数据成员时,其对象大小也为1。

如果在类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针指向虚函数表VTable,在32位机器上,一个对象会增加4个字节来存储此指针,它是实现面向对象中多态的关键。而虚函数本身和其他成员函数一样,是不占用对象的空间的。

我们来看下面一个例子:(此例子在Visual C++编译器中编译运行)

#include <iostream>

using namespace std;

class   A  

{  

};  

class   B  

{  

char   ch;  

void   func()  

{  

}  

};  

class   C  

{  

char   ch1;    //占用1字节

char   ch2;   //占用1字节

virtual   void   func()  

{  

}  

};  

class   D  

{  

int   in;  

virtual   void   func()  

{  

}  

};  

void   main()  

{  

A   a;

B   b;

C   c;

D   d;

cout<<sizeof(a)<<endl;//result=1  

cout<<sizeof(b)<<endl;//result=1   //对象c扩充为2个字,但是对象b为什么没扩充为1个字呢?大家帮忙解决

cout<<sizeof(c)<<endl;//result=8  

//对象c实际上只有6字节有用数据,但是按照上面第二点编译器优化,编译器将此扩展为两个字,即8字节

cout<<sizeof(d)<<endl;//result=8  

  

综上所述:

一个类中,虚函数、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的。

对象大小=   vptr(可能不止一个)   +   所有非静态数据成员大小   +   Aligin字节大小(依赖于不同的编译器)

 

#include <iostream>

using namespace std;

 

class demo1{

 

};

 

class demo2{

    static int num;

};

 

class demo3{

    virtual int print(){}

    virtual int print1(){}

};

 

class demo4{

 

    void print(){}

    static void print1(){}

};

 

class demo5{

    char a;

};

 

int _tmain(int argc, _TCHAR* argv[])

{  

    cout<<"空类的大小为:"<<sizeof(demo1)<<endl;

    //当类不包含虚函数和非静态数据成员时,其对象大小也为1。

    cout<<"当类不包含虚函数和非静态数据成员时,其对象大小也为:"<<sizeof(demo2)<<endl;

 

    cout<<"与类中虚函数的个数无关"<<sizeof(demo3)<<endl;    //大小是4,与类中虚函数的个数无关,

    cout<<"成员函数(静态和非静态)也不占用类对象的存储空间"<<sizeof(demo4)<<endl;

    cout<<sizeof(demo5)<<endl;

    demo5 d;

    cout<<sizeof(d)<<endl;

    return 0;

}

 

  

时间: 2024-09-20 15:18:32

一个类的实例化对象所占空间的大小的相关文章

java中基本类型封装对象所占内存的大小(转)

这是一个程序,java中没有现成的sizeof的实现,原因主要是java中的基本数据类型的大小都是固定的,所以看上去没有必要用sizeof这个关键字. 实现的想法是这样的:java.lang.Runtime类中有一些简单的能涉及到内存管理的函数: Every Java application has a single instance of class Runtime that allows the application to interface with the environment in

如何查看用户表所占空间的大小

如何查看用户表所占空间的大小? 说明:  SQL> col SEGMENT_NAME format a20 SQL> col TABLESPACE_NAME format a20 SQL> select segment_name,tablespace_name,bytes,blocks from user_segments where segment_type='TABLE';

【导入导出】compress 值为y对导入对象所占空间的影响

我们知道 compress 默认Y 将第一个区占原有表的大小加compress=n 就取消了这种压缩,没有数据的话,空间也不会占用那么大了. 下面两篇文章,将分别讲述 compress=Y/N 时 导入表对表空间的占用情况.yang@ORACL> create table bigtab as select * from all_objects; 表已创建. 已用时间:  00: 00: 08.79 yang@ORACL> insert into bigtab select * from big

【导入导出】compress 值为n对导入对象所占空间的影响

下面是我做的实验,在rows =n compress=n 时,最终导入的表 yang 所占的空间是65535! yang@ORACL> create table yang as select * from all_objects; 表已创建. yang@ORACL> insert into yang select *  from yang; 已创建67973行. yang@ORACL> insert into yang select *  from yang; 已创建135946行. y

一个Java对象到底占多大内存?(转)

最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好:http://yueyemaitian.iteye.com/blog/2033046,里面提供的这个类也非常实用: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

struct-sizeof() 如何得到C++类/结构中成员所占空间大小???

问题描述 sizeof() 如何得到C++类/结构中成员所占空间大小??? !!!!请勿答非所问 !!!!! 简要如下: struct XXX { .... ... char strname[****]; ... void funxx() { int iix = sizeof(strname);//这里没问题,问题在下面 } }; int main() { XXX var; int iix2 = sizeof(var.strname);//这也可以, //问题在这里,如何不创建类的实例,也不在类

c#中定义三个类,在第二个类中实例化第一个类,怎样在第三个类中存数据到第二个类实例的第一个类。

问题描述 c#中定义一个点的数组类,然后在另一个类中实例化点并赋值点的x,y,然后再另外建一个类读取点的近似坐标,怎样把近似坐标存入之前的那个已经有了x,y的点数组?求大神!!! 解决方案 解决方案二:第二个类中将第一个类的实例属性public出来,或者暴露相关设置方法解决方案三:list<T>解决方案四:如果把你提到的类,依次标记为clsA,clsB,clsC,那么clsB至少含有字段privateclsAxxx,privateList<clsA>xxx,分别是:存储点,存储近似

如何查看java一个类的大小

问题描述 如何查看java一个类的大小 就比如我搞了一个类,然后往里边set各种值,我现在想知道这个类的占空间的大小?比如多少KB或者多少MB什么的? 解决方案 如果你知道你的类的路径的话,例如D:aa.txt 那么就 public static void main(String[] args) { FileInputStream fis = null; try { fis = new FileInputStream(new File("D:\aa.txt")); } catch (F

饿汉式的非延迟实例化对象怎么理解

问题描述 classSingleton{privatestaticSingletoninstance=newSingleton();privateSingleton(){}publicstaticSingletongetInstance(){returninstance;}} 在没有类初始化之前newSingleton()应该是不会被实例化.是由当<cinit>方法触发即类初始化进行时才会new.而类主动初始化仅有的如下几种情况,详见<深入理解java虚拟机>7.2节类加载的时机1