C++中的内存区域及其性能特征

首先需要指出的是,我们通常用“堆”和“自由存储”这两个术语来区分两种不同类型的动态分配内存。

1.常量数据:常量数据区域主要用于存储字符串以及其他在编译期就已经知道值的数据。实例化的对象是不能存储在 这 个区域中的。

在程序的整个生存期内,这个区域中的所有数据都是有效的。而且,所有这些数据都是只读的,如果对这些数据进行修改,其结果在C++中是没有定义的。造成这种后果的部分原因是编译器可能会对常量数据的基本存储格式进行任意优化。例如,在某个特定的编译器中,可能会将字符串常量保存在重叠对象内以进行优化。

2.栈:在栈中存储的是自动变量。自动变量在定义的时候被立即构造,并且在自动变量作用域结束的时候被立即销毁,因此程序员无法对已经分配但尚未初始化的栈空间直接进行操作(除非你有意识地使用显示析构函数和布局new语法)。

栈内存的分配通常要比动态内存的分配(堆和自由存储)快很多,因为每次栈内存的分配只涉及栈指针的自增操作,而无需进行更为复杂的内存管理。

3.自由存储:自由存储时两种动态内存区域之一,它是通过new/delete来分别进行分配/释放。

对象的生存期可能会小于所分配的存储空间的生存期。也就是说,自由存储区域中的对象在分配内存时并不要求立即进行初始化,而且在销毁对象时,也不要求立即释放内存空间。在存储空间已经被分配但还没有进入到对象生存期的这段时间内,我们可以通过一个void*类型的指针来访问和操作这块存储空间,但我们不能访问对象中任何一个非静态的成员或非静态的成员函数,不能去获得他们的地址,或者进行其他的操作。

4.堆:堆是另一种动态内存区域,它是通过malloc()/free()函数以及这些函数的其他形式来进行分配/释放的。

我们要注意的是,尽管在某个特定的编译器中,默认的全局运算符new和delete可能会用函数malloc()和free()来进行实现,但是堆还是不同于自由存储,在堆中分配的内存不能再自由存储区域中被安全地释放,反之亦然 在堆中分配的内存,可以用于对象的placement new构造过程 和显示的析构过程中。如果是这种用法,那么自由存储区域中关于对象生存期的注意事项也同样适用于堆。

5.全局/静态:在程序启动的时候,这些变量/对象或静态的变量/对象就已经被分配了存储空间,但只有等到程序执行的时候,这些变量/对象才可以进行初始化。例如:函数中的静态变量只有当程序第一次执行到变量的定义语句时才能被初始化。

对于跨越多个编译单元的全局变量,它们的初始化顺序是未定义的,并且我们在管理全局对象(包括类的静态成员)之间的依赖性的时候要特别小心。通常来说,我们可以通过一个void*指针来对未初始化的对象存储空间进行访问和操作,但我们不能再对象的生存期之外来使用或者引用非静态的成员变量或成员函数。

指导原则:我们应该优先使用自有存储(new/delete),并且要避免去使用堆(malloc/free)。



C++中的内存区域及其性能特征

时间: 2025-01-11 19:27:08

C++中的内存区域及其性能特征的相关文章

C++中的内存区域

常量数据:常量数据区域主要用于存储字符串以及其他在编译期就已经知道值得数据.实例化的对象不能存储在这个区域. 在程序的整个生存期内,这个区域中的所有数据都有效,而且都是只读的,对这些数据进行修改的结果在C++中是没有定义的.一部分原因是编译器可能会对常量数据的基本存储格式进行任意的优化.例如,在某个特定的编译器中,可能会将字符串常量保存在重叠对象中以进行优化. 栈:在栈中存储的是自动变量.自动变量在定义时将被立即构造,并且在其作用域结束时被立即销毁,因此程序员无法对已经分配但尚未初始化的栈空间直

JVM中各内存区域解释,以及变量的作用域解释

转载自:http://blog.csdn.net/zz87250976/article/details/42875301 JVM内存分四种:1.栈区(stacksegment)—由编译器自动分配释放,存放函数的参数值,局部变量的值等,具体方法执行结束之后,系统自动释放JVM内存资源:2.堆区(heapsegment)—一般由程序员分配释放,存放由new创建的对象和数组,jvm不定时查看这个对象,如果没有引用指向这个对象就回收:3.静态区(datasegment)—存放全局变量,静态变量和字符串常

JVM性能优化系列-(1) Java内存区域

1. Java内存区域 1.1 运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.主要包括:程序计数器.虚拟机栈.本地方法栈.Java堆.方法区(运 行时常量池).直接内存. 程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器.在虚拟机概念模型中,字节码解释器工作时就是通过改变计数器的值来选取下一条需要执行的字节码指令,分支.循环.跳转.异常处理.线程恢复等

JVM的内存区域划分以及垃圾回收机制详解

在我们写Java代码时,大部分情况下是不用关心你New的对象是否被释放掉,或者什么时候被释放掉.因为JVM中有垃圾自动回收机制.在之前的博客中我们聊过Objective-C中的MRC(手动引用计数)以及ARC(自动引用计数)的内存管理方式,下方会对其进行回顾.而目前的JVM的内存回收机制则不是使用的引用计数,而是主要使用的"复制式回收"和"自适应回收". 当然除了上面是这两种算法外,还有其他是算法,下方也将会对其进行介绍.本篇博客,我们先简单聊一下JVM的区域划分,

java内存区域/内存溢出汇总

本文主要介绍Java虚拟机中的内存区域与各种内存溢出情况汇总. 数据区域 方法区.堆.虚拟机栈.程序计数器.本地方法栈 方法区 用于存储已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码 运行时常量池:存放编译期生成的字面量和符号引用 异常(OutofMemoryError: PermGen space)产生原因:1.往常量池中添加大量数据.eg:String.intern()2.大量的类信息(或者动态代理) 异常处理:适当增大配置:-XX:PermSize -XX:MaxPermS

jvm内存区域----线程共享区

一.堆的含义 jvm堆的区域主要是用来存放对象的实例,它的空间大小是JVM内存区域中占比重最大的,也是jvm最大的内存管理模块,最重要的是,这个区域是垃圾收集器主要管理的区域,这意味着我们在考虑垃圾回收优化的时候,首先就要想到堆中的区域. 二.方法区 方法区同样是jvm的内存区域,它和堆一样,都是线程共享区中的内存区域.方法区都主要存放的是jvm加载的类信息.常量.静态变量.及时编译的代码类信息(这里面主要有:1.类型的版本 2字段 3方法 4接口 5常量池).在方法区中,一般不进行垃圾回收,因

java中的内存分配原则

问题:Java中这些类.变量.字符串.方法,在内存中是怎样分配的? 首先,Java中的内存区域如下: ◆寄存器:我们在程序中无法控制 ◆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中.当在一段代码块定义一个变量时,Java就在栈中 为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用.实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针! ◆堆:存放用new产生的数据.在堆中分配的内存,由J

[Spark性能调优] 第四章 : Spark Shuffle 中 JVM 内存使用及配置内幕详情

本课主题 JVM 內存使用架构剖析 Spark 1.6.x 和 Spark 2.x 的 JVM 剖析 Spark 1.6.x 以前 on Yarn 计算内存使用案例 Spark Unified Memory 的运行原理和机制 引言 Spark 从1.6.x 开始对 JVM 的内存使用作出了一种全新的改变,Spark 1.6.x 以前是基于静态固定的JVM内存使用架构和运行机制,如果你不知道 Spark 到底对 JVM 是怎么使用,你怎么可以很有信心地或者是完全确定地掌握和控制数据的缓存空间呢,所

jvm中堆栈以及内存区域分配

堆栈这个概念存在于数据结构中,也存在于jvm虚拟机中,在这两个环境中是截然不同的意思. 在数据结构中,堆栈是:堆 和栈两种数据结构,堆是完全二叉树,堆中各元素是有序的.在这个二叉树中所有的双亲节点和孩子节点存在着大小关系,如所有的双亲节点都大于孩子节点则 为大头堆,如果所有的双亲节点都小于其孩子节点说明这是一个小头堆,建堆的过程就是一个排序的过程,堆得查询效率也很高.栈是一种先进后出的线性表. 在jvm虚拟机中得堆栈对应内存的不同区域,和数据结构中所说的堆栈是两码事. 下面介绍jvm中得堆栈以及