imicman的个人空间 https://blog.eetop.cn/1518355 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

c++类实例在内存中的分配 (转)

已有 1199 次阅读| 2017-5-19 09:37 |个人分类:杂谈|系统分类:芯片设计

关于结构体和C++类的内存地址问题

今天终于有时间写点 东西了~ 太爽了  *_*  很多人都知道C++类是由结构体发展得来的,所以他们的成员变量(C语言的结构体只

有成员变量)的内存分配机制是一样的。下面我们以类来说明问题,如果 类的问题通了,结构体也也就没问题啦。 类分为成员变

量和成员函数,我们先来讨论成员变量。 一个类对象的地址就是类所包含的这一片内存空间的首地址,这个首地址也就对应具体

某一个成员变量的地址。(在定义类对象的同时这些成员变量也就被定义了)我们来以一段代码说明问题: //类的定义

class K{
public:
 K(){k = 12;}
 ~K(){}
 int k;
}; 

//类的使用//... K kTemp;
 printf("%d--%d\n",&kTemp,&kTemp.k);
 printf("%d--%d\n",sizeof(K),sizeof(kTemp.k));
 int *i = (int*)(&kTemp);
 int w = *i;
 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)

    class  A

   {

     public:

          int i;

   }

  

   类A的实例将占据4个字节的内存,sizeof(A) = 4

   变量i 的初值被编译器指定位0xcdcdcdcd。

    再增加一个变量,

   class A

   {

      public:

      int  i;

      int  l;

   }

   此时按照变量生命的先后顺序,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.

 再看下面这个情况

 class A

 {

      public:

         int i;

         int l;

         static int s;

         int add(int x,int y){return (x+y)};

 };

此时sizeof(A)大小仍为8,这里留给读者去思考为什么?(^-^)。

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

 class A

 {

      public:

         int i;

         int l;

         static int s;

         virtual void Say(){};

         int add(int x,int y){return (x+y)};

 };

 因为含有虚函数,所以类里面将含有一个虚指针vptr,指向该类的虚表vtbl,一个指针占用四字节的地址,所以sizeof(A) = 12

 虚指针放在类实例地址的最低位置,

 比如 A *a = new A;

 我们可以这样给变量i赋值

int *p = (int *)a;
 p++;
 *p = 1;//把i的值赋为1.

如果类作为派生类,内存将如何分配呢?

这种情况虽然有些复杂,但并不是说不好理解。

他有多少个父类每个父类的大小加起来在加上自身就是sizeof的大小。

 

点赞

发表评论 评论 (2 个评论)

回复 imicman 2017-5-19 09:38
http://www.cnblogs.com/bizhu/archive/2012/09/25/2701691.html
回复 imicman 2017-5-19 09:51
http://www.cnblogs.com/jerry19880126/p/3616999.html

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 1

    粉丝
  • 0

    好友
  • 8

    获赞
  • 34

    评论
  • 访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-17 22:15 , Processed in 0.012968 second(s), 13 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部