关于C++中类的占用内存大小

来源:互联网 发布:combo端口 编辑:程序博客网 时间:2024/05/16 06:30

所有的函数都是存放在代码区的,不管是全局函数,还是成员函数。sizeof访问的程序的数据段。

1. 类的大小为类的非静态成员数据的类型大小之和,也 就是说静态成员数据不作考虑。

2. 普通成员函数与sizeof无关。

3. 静态成员并不属于某个对象,sizeof取的是对象大小。

4. 虚函数由于要维护在虚函数表,所以要占据一个指针大小,也就是4字节。

5. 空类的sizeof为1。因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含 的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。

6. Sizeof(类名)是在编译时就计算了的,一个类定义了,它所占的内存编译器就已经知道了,这时只是得到它占用的大小,并没有分配内存操作 。也可以这样想:编译器肯定知道大小了,这与分配内存空间无关,知道大小了,以后实例化了才能知道要分配多大。

类是抽象的,是不占有内存的,可是如果类生成实例那么将会在内存中分配一块内存来存储这个类。

7. 类的总大小也遵守类似class字节对齐的,调整规则。

8. 静态成员函数与一般成员函数的唯一区别就是没有this指针,因此不能访问非静态数据成员。


以下转自:http://blog.csdn.net/chenyiming_1990/article/details/10308507

关于结构体和C++类的内存地址问题
C++类是由结构体发展得来的,所以他们的成员变量(C语言的结构体只有成员变量)的内存分配机制是一样的。下面我们以类来说明问题,如果类的问题通了,结构体也也就没问题啦。 类分为成员变量和成员函数,我们先来讨论成员变量。 一个类对象的地址就是类所包含的这一片内存空间的首地址,这个首地址也就对应具体某一个成员变量的地址。(在定义类对象的同时这些成员变量也就被定义了)我们来以一段代码说明问题:

[cpp] view plaincopyprint?
  1. class K  
  2. {  
  3.    public:  
  4.       K(){k = 12;}  
  5.       ~K(){}  
  6.       int k;  
  7. };   
  8.   
  9. K kTemp;  
  10. printf("%d--%d\n",&kTemp,&kTemp.k);  
  11. printf("%d--%d\n",sizeof(K),sizeof(kTemp.k));  
  12. int *i = (int*)(&kTemp);  
  13. int w = *i;  
  14. printf("%d\n",w);   
运行上面的代码,结果如下:
1310588--1310588
4--4
12
很明显,类的内存大小和其唯一的成员变量的内存大小是一致的。内存地址也是一致的。他们甚至可以相互转换。换成结构体结果也是一样。。那么成员函数又如何?上面得代码就好像类没有任何成员函数一样,根本说明不了问题。 呵呵,所有的函数都是存放在代码区的,不管是全局函数,还是成员函数。要是成员函数占用类的对象空间,那么将是多么可怕的事情:定义一次类对象就有成员函数占用一段空间。 我们再来补充一下静态成员函数的存放问题吧:静态成员函数与一般成员函数的唯一区别就是没有this指针,因此不能访问非静态数据成员,就像我前面提到的,所有函数都存放在代码区,静态函数也不例外。所有有人一看到 static 这个单词就主观的认为是存放在全局数据区,那是不对的

c++是一种面向对象的编程语言,它向下保持了对c的兼容,同时也允许程序员能够自由的操控内存,虽然会带来一些问题,但这不是我们要探讨的问题,略过不表。类是对某种对象的定义,包含变量和方法,也可以理解为现实生活中一类具有共同特征的事务的抽象,他是面向对象语言的基础。所以类是不占有内存的,可是如果类生成实例那么将会在内存中分配一块内存来存储这个类。
类的实例在内存中是如何分配内存的,有什么需要我们注意的,下面将慢慢到来。

比如下面一个类:
class A
{};
从形式上看,它似乎什么有没有,事实上它不止隐含了一个构造函数和一个析构函数,还有一些操作符重载函数,比如“=”。如果类A被实例话,如A a;在内存会占据多大的空间呢?有人可能会说4,也有人会说0,还有人会说1,说1的就对了,为什么会是1呢?原因有很多,如果我们定义一个数组A b[10];如果上面是0,这样的局面将会很尴尬,所以A这样一个空类,编译器会给它一个字节来填充。

增加一个变量,(字节对齐默认都是4)

[cpp] view plaincopyprint?
  1. class A  
  2. {  
  3.      public:  
  4.      int i;  
  5. }  
类A的实例将占据4个字节的内存,sizeof(A) = 4
变量i 的初值被编译器指定位0xcdcdcdcd。

再增加一个变量,

[cpp] view plaincopyprint?
  1. class A  
  2. {  
  3.    public:  
  4.       int i;  
  5.       int l;  
  6. }  
此时按照变量生命的先后顺序,i被放在低地址上,l紧随其后。
实例占用8个字节,sizeof(A) = 4*2 = 8

如果类里面含有函数:
class A
{
public:
int i;
int l;
int add(int x,int y){return (x+y);}
};
有些人可能会说类的大小是12,事实上sizeof(A) = 8;
为什么会这样,这是因为sizeof访问的程序的数据段,而函数地址则被保存在代码段内,所以最后的结果是8.
再看下面这个情况

[cpp] view plaincopyprint?
  1. class A  
  2. {  
  3.    public:  
  4.       int i;  
  5.       int l;  
  6.       static int s;  
  7.       int add(int x,int y){return (x+y)};  
  8. };  
此时sizeof(A)大小仍为8,这里留给读者去思考为什么?(^-^)。

当类里面含有虚函数时,情况会如何呢?

[cpp] view plaincopyprint?
  1. class A  
  2. {  
  3.    public:  
  4.      int i;  
  5.      int l;  
  6.      static int s;  
  7.      virtual void Say(){};  
  8.      int add(int x,int y){return (x+y)};  
  9. };  
因为含有虚函数,所以类里面将含有一个虚指针vptr,指向该类的虚表vtbl,一个指针占用四字节的地址,所以sizeof(A) = 12
虚指针放在类实例地址的最低位置,
比如 A *a = new A; 
我们可以这样给变量i赋值
int *p = (int *)a;
p++;
*p = 1;//把i的值赋为1.
如果类作为派生类,内存将如何分配呢?
这种情况虽然有些复杂,但并不是说不好理解。
他有多少个父类每个父类的大小加起来在加上自身就是sizeof的大小。
0 0
原创粉丝点击