【转载】C++类成员函数在内存中的存储方式
对象所占用的存储空间存储:类成员变量、虚函数表指针(vfptr),类的成员函数存储在 代码区
看如下测试代码:
class D { public: void printA() { cout<<"printA"<<endl; } virtual void printB() { cout<<"printB"<<endl; } }; int main(void) { D *d=nullptr; d->printA(); d->printB(); }
问题:以上代码的输出结果是什么?
答案是输出“printA”后,程序崩溃。类中包括成员变量和成员函数。new出来的只是成员变量,成员函数始终存在,所以如果成员函数未使用任何成员变量的话,不管是不是static的,都能正常工作。
printB()为虚函数,虚函数表指针存在类的对象中,此处类对象未实例化,所以无法获得虚函数表指针,从而无法获得printB()函数的指针,无法运行printB()函数。
C++程序的内存格局通常分为四个区:全局数据区(data area),代码区(code area),栈区(stack area),堆区(heap area)(即自由存储区)。全局数据区存放全局变量,静态数据和常量;所有类成员函数和非成员函数代码存放在代码区;为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区;余下的空间都被称为堆区。根据这个解释,我们可以得知在类的定义时,类成员函数是被放在代码区,而类的静态成员变量在类定义时就已经在全局数据区分配了内存,因而它是属于类的。对于非静态成员变量,我们是在类的实例化过程中(构造对象)才在栈区或者堆区为其分配内存,是为每个对象生成一个拷贝,所以它是属于对象的。
静态成员函数和非静态成员函数的区别:
静态成员函数和非静态成员函数都是在类的定义时放在内存的代码区的,因而可以说它们都是属于类的,但是类为什么只能直接调用静态类成员函数,而非静态类成员函数(即使函数没有参数)只有类对象才能调用呢?
原因是:
当类的非静态类成员函数的参数中包括类的成员变量时,此时还会包含一个指向类对象的指针类型参数(即this指针),此时只有类对象才能调用非静态类成员函数(此时this指针有实值)。
需要说明,不论成员函数在类内定义还是在类外定义,成员函数的代码段都用同一种方式存储。不要将成员函数的这种存储方式和inline(内联)函数的概念混淆。不要误以为用inline声明(或默认为inline)的成员函数,其代码段占用对象的存储空间,而不用inline声明的成员函数,其代码段不占用对象的存储空间。不论是否用inline声明(或默认为inline),成员函数的代码段都不占用对象的存储空间。用inline声明的作用是在调用该函数时,将函数的代码段复制插人到函数调用点,而若不用inline声明,在调用该函数时,流程转去函数代码段的入口地址,在执行完该函数代码段后,流程返回函数调用点。inline与成员函数是否占用对象的存储空间无关,它们不属于同一个问題,不应搞混。
————————————————
版权声明:本文为CSDN博主「GeorgiaStar」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fuzhongmin05/article/details/59112081

浙公网安备 33010602011771号