问大家一道题:关于成员函数占多少内存解决方法

问大家一道题:关于成员函数占多少内存类的对象的内存布局,里面会有数据成员,但是没有函数成员(充其量里面

问大家一道题:关于成员函数占多少内存
类的对象的内存布局,里面会有数据成员,但是没有函数成员(充其量里面可能有个vptr),难道类的成员函数本身不占内存?

这是第一个疑问,请教高手:成员函数不占内存吗?推而广之,一般的全局函数不占内存吗?如果占,那么函数该占多少内存,与什么有关(参数?还是函数体里的局部变量?)


第二个问题:
如果外层用一个int** 指针,去访问类的虚函数,我可以做到,但是无法访问类的normal函数,请问高人,能否做到:

#include <stdio.h>
typedef void (*PTRFUN)(void);//声明一个函数指针

class A
{
public:
int ia;
int ib;
void virtual fun1();//虚函数
void virtual fun2();
void virtual fun3();
void virtual fun4();
void fun5();//实函数,normal
A();
};
A::A()
{
  ib=20;
  ia=10;
}
void A::fun1()
{
printf("A::fun1()\n");
}
void A::fun2()
{
  printf("A::fun2()\n");
}
void A::fun3()
{
  printf("A::fun3()\n");
}
void A::fun4()
{
  printf("A::fun4()\n");
}
void A::fun5()
{
  printf("A::fun5()\n");
}


void main()
{

  A b;
  int **ptr=NULL;
  ptr=(int **)&b;

  PTRFUN ptrfun; 

  printf("ptr[0][0]=%d\n",(int)(ptr[0]));//这是强行解释vptr,没什么意义
  printf("ptr[0][2]=%d\n",(int)(ptr[1]));//访问ia
  printf("ptr[0][3]=%d\n",(int)(ptr[2]));//访问ib

  //这是强行解释之后的编码,我是边调试边写的,顺便就能得出b的内存布局来
  //这样能访问虚函数们
  ptrfun=(PTRFUN)(ptr[0][0]);
  ptrfun();//访问fun1
  ptrfun=(PTRFUN)(ptr[0][1]);
  ptrfun();//访问fun2
  ptrfun=(PTRFUN)(ptr[0][2]);
  ptrfun();//访问fun3
  ptrfun=(PTRFUN)(ptr[0][3]);
  ptrfun();//访问fun4
  //我该如何访问fun5?
}

上面这个,如何通过ptr来访问fun5?是不是因为fun5不在对象内存中,因此无法访问得到?
请真正的高手进来解答我的疑问


(注:上面的代码,我采用了一种“投机取巧”的方式,那就是int和int*占的内存大小一样大。。。。要不然,收不到效果的)
我用的VC6.0+XP32位系统

[解决办法]
你现在应该不是研究这个的时候,你所说的函数占的内存都是到了运行期才占的,而在编译器编译好之后就放到比如PE文件的.text段。 运行的时候就会将该段加载到内存(内存权限只能执行)。至于你说的对象的内存,这个是运行的时候随着函数栈帧来进行构造销毁。总之这不是你现在应该研究的内容
[解决办法]

探讨
引用:
第一个问题,任何函数都不占内存,成员函数除了要多push一个this指针之外,和非成员函数没有任何区别,都是编译的时候就生成函数体的二进制码了,直接放在程序的代码段。

第二个问题,虚函数由于C++语法的规定,调用的时候必须先检索vtable然后再动态的跳转,没法把具体call的地址直接硬编码到代码中,所以才会在每个类的实例中插入一个vptr,而lz所谓的"norm……

[解决办法]
对象的内存是这样的:
代码段:成员函数代码
堆:静态成员变量
对象本身:非静态成员变量,虚函数入口表(如果存在至少一个虚函数)

成员函数有一个专用参数this,是编译器偷偷加进去的,指向对象本身,如果没有冲突,访问成员变量可以省略this->

虚函数从虚函数入口表获得函数指针,其他函数入口点编译时是知道的。

你肯钻研但是读书太少,所谓思而不学则罔,说的就是你这种情况。
[解决办法]
仅供参考
C/C++ code
//仅对VC6#include <stdio.h>void fun1() {    int f1=1;    printf("fun1\n");    printf("fun1\n");}void fun2() {    int f2=2;    printf("fun2\n");}void fun3() {}void main() {#ifdef _DEBUG    printf("sizeof(fun1)==%d\n",*(int *)((int)fun2+1)-*(int *)((int)fun1+1));    printf("sizeof(fun2)==%d\n",*(int *)((int)fun3+1)-*(int *)((int)fun2+1));//sizeof(fun1)==59//sizeof(fun2)==43#else    printf("sizeof(fun1)==%d\n",(int)fun2-(int)fun1);    printf("sizeof(fun2)==%d\n",(int)fun3-(int)fun2);//sizeof(fun1)==32//sizeof(fun2)==16#endif}
[解决办法]
typedef void (A::*Myfun)(void) ;
[解决办法]
探讨
你推荐几本好书吧 关于这一类问题的 <深入探索c++对象模型>就不必推荐了


[解决办法]
函数的二进制码在代码段的吧 运行的时候已经分配好了 所有的成员函数的调用都是用地址来调用其中的二进制码 函数名字仅仅只是一个符号而已 编译后就替换掉了 所以无论是成员函数还是静态函数 在编译后仅仅是个普通函数而已 调用的规则是在c++语法层面上的

占内存的是对象的成员,假设在栈上分配 ,则堆栈段会分配相应大小的内存 堆上分配的话 栈上分配一个指针大小的内存用于记录堆上的地址 对象的成员函数是不占数据区的内存的
[解决办法]
自己写个类(成员,函数,函数里面最好有些超级简单明白的代码,自己一眼就能看出来的那种),然后实例(要是麻烦,就给各个成员赋值成规则的数字,便于自己发现),

编译运行,输出实例的地址,然后记着地址,然后去调试器看内存结构...

实例:数据1,数据2数据3,...函数1地址,函数2地址,函数3地址,
...
函数1:{各种代码...}
函数2:{各种代码...}
...

实例可以在堆栈,堆...函数1,函数2都在程序代码段.
[解决办法]
我觉得,看《深入理解计算机系统》比看《深度探索c++对象模型》更能消除你的困惑。
赵大牛的代码,是不会给你带来任何知识的。
[解决办法]
每个程序都会有4G的虚拟内存,当程序运行时,系统会分配物理空间 形成映射,与虚拟内存对应起来

程序都有5个数据段
全局区:初始化的全局变量,静态的变量
代码区:主要是存放函数,还有一些 char* 的常量(可读不可改的)
BBS段: 未初始化的全局变量,运行时,都会清零
堆区:自己分配出来的内存 ,new /malloc/sbrk/等(必须自己释放,要不就内存泄露)
栈区:函数内部定义的局部变量,