C++成员函数在内存中的存储方式
用类去定义对象时,系统会为每一个对象分配存储空间。如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间。按理说,如果用同一个类定义了10个对象,那么就需要分别为10个对象的数据和函数代码分配存储单元,如下图所示。

能否只用一段空间来存放这个共同的函数代码段,在调用各对象的函数时,都去调用这个公用的函数代码。如下图所示。

显然,这样做会大大节约存储空间。C++编译系统正是这样做的,因此每个对象所占用的存储空间只是该对象的数据部分(虚函数指针和虚基类指针也属于数据部分)所占用的存储空间,而不包括函数代码所占用的存储空间。
看如下测试代码
class D
{
public:
void printA()
{
cout<<"printA"<<endl;
}
virtual void printB()
{
cout<<"printB"<<endl;
}
};
int main(void)
{
D *d=NULL;
d->printA();
d->printB();
}
问题:以上代码的输出结果是什么?
C++程序的内存格局通常分为四个区:全局数据区(data area),代码区(code area),栈区(stack area),堆区(heap area)(即自由存储区)。全局数据区存放全局变量,静态数据和常量;所有类成员函数和非成员函数代码存放在代码区;为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区;余下的空间都被称为堆区。根据这个解释,我们可以得知在类的定义时,类成员函数是被放在代码区,而类的静态成员变量在类定义时就已经在全局数据区分配了内存,因而它是属于类的。对于非静态成员变量,我们是在类的实例化过程中(构造对象)才在栈区或者堆区为其分配内存,是为每个对象生成一个拷贝,所以它是属于对象的。
应当说明,常说的“某某对象的成员函数”,是从逻辑的角度而言的,而成员函数的存储方式,是从物理的角度而言的,二者是不矛盾的。
下面我们再来讨论下类的静态成员函数和非静态成员函数的区别:静态成员函数和非静态成员函数都是在类的定义时放在内存的代码区的,因而可以说它们都是属于类的,但是类为什么只能直接调用静态类成员函数,而非静态类成员函数(即使函数没有参数)只有类对象才能调用呢?原因是类的非静态类成员函数其实都内含了一个指向类对象的指针型参数(即this指针),因而只有类对象才能调用(此时this指针有实值)。
回答开头的问题,答案是输出“printA”后,程序崩溃。类中包括成员变量和成员函数。new出来的只是成员变量,成员函数始终存在,所以如果成员函数未使用任何成员变量的话,不管是不是static的,都能正常工作。需要注意的是,虽然调用不同对象的成员函数时都是执行同一段函数代码,但是执行结果一般是不相同的。不同的对象使用的是同一个函数代码段,它怎么能够分别对不同对象中的数据进行操作呢?原来C++为此专门设立了一个名为this的指针,用来指向不同的对象。
需要说明,不论成员函数在类内定义还是在类外定义,成员函数的代码段都用同一种方式存储。不要将成员函数的这种存储方式和inline(内联)函数的概念混淆。不要误以为用inline声明(或默认为inline)的成员函数,其代码段占用对象的存储空间,而不用inline声明的成员函数,其代码段不占用对象的存储空间。不论是否用inline声明(或默认为inline),成员函数的代码段都不占用对象的存储空间。用inline声明的作用是在调用该函数时,将函数的代码段复制插人到函数调用点,而若不用inline声明,在调用该函数时,流程转去函数代码段的入口地址,在执行完该函数代码段后,流程返回函数调用点。inline与成员函数是否占用对象的存储空间无关,它们不属于同一个问題,不应搞混。
C++成员函数在内存中的存储方式的更多相关文章
- QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用
FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QL ...
- <转载>浅谈C/C++的浮点数在内存中的存储方式
C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在Intel CPU架构的系统中 ...
- C语言中浮点数在内存中的存储方式
关于多字节数据类型在内存中的存储问题 //////////////////////////////////////////////////////////////// int ,short 各自是4. ...
- Float在内存中的存储方式及IEC61131处理
Float在内存中的存储方式及IEC61131处理 1,fp32(32bits float)类型数据在存储器中占用4Bytes存储,且遵循IEEE-754标准: 一个浮点数分三部分组成: 符号位s(1 ...
- 数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)
https://www.cnblogs.com/renyuan/archive/2013/05/26/3099766.html 1.故事的起源 “endian”这个词出自<格列佛游记>.小 ...
- 实验:使用GDB查看结构体在内存中的存储方式
结构体在内存中的表示形式是怎么样的? 结构体在内存中和普通变量存储没有太大的区别. 首先我们看看,计算机如何读取普通变量: 普通变量例如int是占据4个字节,计算机读内存的时候会从起始地址开始读, ...
- C/C++浮点数在内存中的存储方式
一.内存表示 任何数据在内存中都是以二进制的形式存储的,浮点数的表示是把一个数的有效数字和数的范围在计算机的一个存储单元中分别予以表示,数的小数点位置随比例因子的不同而在一定范围内自由浮动.如下图是3 ...
- float和double在内存中的存储方式
本文转载于:http://wenku.baidu.com/link?url=ARfMiXVHCwCZJcqfA1gfeVkMOj9RkLlR9fIexbgs9gDdV8rIS48A1_xe1y6YgX ...
- C/C++数据在内存中的存储方式
目录 1 内存地址 2 内存空间 在学习C/C++编程语言时,免不了和内存打交道,在计算机中,我们存储有电影,文档,音乐等数据,这些数据在内存中是以什么形式存储的呢?下面做一下简单介绍. 本文是学 ...
随机推荐
- c# ef
找出不同项 ).ToList(); resultMsg = string.Join(",", query.select(p=>p.key).ToList())
- C++学习(三十七)(C语言部分)之 链式栈(推箱子实现)
用链表实现栈一开始在表头插入,就要一直在表头插入一开始在表尾插入,就要一直在表头插尾表头当栈底 也可以把表尾当栈底 实现的测试代码笔记如下: #include<stdio.h> #incl ...
- flask,gunicorn,supervisor,nginx配置服务器接口
1,申请阿里云主机 2,apt-get update 3,apt-get install pip 4,pip install virtualenv 5,virtualenv venv 6,source ...
- pass
空语句 do nothing 保证格式完整 保证语义完整 以if语句为例,在c或c++/java中: if(true) ; //do nothing else { //do something } 1 ...
- Python的深copy和浅copy
浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象. 浅copy: a = [1, 2, ...
- 如何将极客时间课程制作成kindle电子书
订阅了几个极客时间的专栏,一直没有时间去看. 最近,想着如果把内容制作成电子书,利用上下班时间学习一下,岂不是很方便? 在网上搜到一个很好用的开源软件,几分钟就可以把极客时间的专栏做成电子书,简直太棒 ...
- Oauth2.0客户端服务端示例
https://blog.csdn.net/qq_28165595/article/details/80459185 前言前面的理解OAuth2.0认证与客户端授权码模式详解,我们大致了解了Oauth ...
- Flask--(项目准备)--添加日志
日志:记录程序运行的状态,在manage.py同级目录下创建logs文件夹 定义日志文件: import logging from logging.handlers import RotatingFi ...
- Zookeeper 在Windows下的安装过程及测试
安装jdk 安装Zookeeper. 在官网http://zookeeper.apache.org/下载zookeeper.我下载的是zookeeper-3.4.6版本. 解压zookeeper-3. ...
- cookie and sesssion
会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...