C++ Primer 笔记——控制内存分配】的更多相关文章

1.当我们使用一条new表达式时,实际执行了三步操作. new表达式调用一个名为operator new ( 或者operator new[] ) 的标准库函数.该函数分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象(或对象的数组) 编译器运行相应的构造函数以构造这些对象,并为其传入初始值. 对象被分配了空间并构造完成,返回一个指向该对象的指针. 2.当我们使用一条delete表达式删除一个动态分配的对象时,实际执行了两步操作. 对指针所指的对象或者数组名所指的数组中的元素执行对…
  1.new和delete表达式的工作机理      1)new表达式实际执行了三步 string *sp=new string("aaaa"); ];//string采用默认初始化      a.调用一个名为operator new(或者operator new[])的标准库函数,分配一块足够大的.原始的.未命名的内存空间,来准备存储对象或者对象的数组:      b.编译器运行相应的构造函数构造这些对象,在这里运行的是string的构造函数:      c.返回一个指向该对象或者…
一.内存分配方式 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区.栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放.栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限.堆:malloc在堆上分配的内存块,使用free释放内存自由存储区:new所申请的内存则是在自由存储区上,使用delete来释放,编译器不管,由程序自己释放,一般一个new就要对应一个 delete.如果程序员没有释放掉,那…
为了满足应用程序对内存分配的特殊需求,C++允许重载new运算符和delete运算符控制内存分配,通过定位new表达式初始化对象(好处是可以在某些场景下避免重新内存分配的消耗) 1.operate new /delete #include "QtGuiApplication2.h" class A { public: A():m_i(){} A(int i):m_i(i){} ~A(){} void* operator new(size_t st) noexcept { if (voi…
重载new和delete 1. 测试代码: #include<iostream> #include<new> using namespace std; class A { public: A() { cout << "A constructor" << endl; } void* operator new(size_t size) { cout << "this is A's new" << e…
一般的内存分配是指堆上的分配,但也可能经过JIT编译后被拆散为标量类型并间接地在栈上分配.对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下直接分配在老年代中,分配的规则并不是百分之百固定的.细节取决于哪一种垃圾收集器组合,还有虚拟机中与内存相关的参数的设置. 一.对象优先在Eden分配 优先在新生代的Eden区中分配,当不够时,发起一次Minor GC. 二.大对象直接进入老年代 需要连续大量内存空间的Java对象,长字符串和数组等. 三.…
JVM在执行Java程序的过程中会把它所管理的内存划分若干个不同的数据区域,如下图: 大致可以分为两类:线程私有区域和线程共享区域. 线程私有区域 程序计数器(Program Counter Register): 是一块很小的内存,可以看做是当前线程所执行的字节码行号指示器,虚拟机根据计数器值获取吓一条要执行的指令. JVM栈:虚拟机栈(JVM stacks),每个方法被执行时都会同时创建一个栈帧(stack frame)用于存储局部变量表.操作数栈.动态连接.方法出口等信息.每一个方法被调用直…
1. 动态内存分配的意义 (1)C 语言中的一切操作都是基于内存的. (2)变量和数组都是内存的别名. ①内存分配由编译器在编译期间决定 ②定义数组的时候必须指定数组长度 ③数组长度是在编译期就必须确定的 (3)但是程序运行的过程中,可能需要使用一些额外的内存空间 2. malloc 和 free 函数 (1)malloc 和 free 用于执行动态内存分配的释放 (2)malloc 所分配的是一块连续的内存 (3)malloc 以字节为单位,并且返回值不带任何的类型信息:void* mallo…
重载new和delete 首先借用C++ Primer 5e的一个例子: string *sp = new string("a value"); ]; 这其实进行了以下三步操作: new表达式调用一个名为operator new(或者operator new[])的标准函数,分配一块足够大的,原始的,未命名的内存空间来存储特定的类型或者对象的数组. 编译器运行相应的构造函数以构造这些对象,并且传入初值. 对象构造完毕后返回指向该对象的指针. 当我们进行下列的语句时: delete sp…
本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. 内存分配一般关注的是对象在堆上分配的情况,对象主要分配在新生代的Eden区中,如果启用了本地线程分配缓冲,将按线程优先在TLAB上分配.少数情况下也会直接分配在老年代中,这取决于使用的垃圾收集器组合,以及设置的JVM参数. 对象优先在Eden分配 大多数情况下,对象在Eden区中分配.当Eden区没有足够空间进行分配时,虚拟机会发起一次Minor GC. Minor GC:发生在新生代的垃圾收…
特殊的工具和技术 --优化内存分配 引言: C++的内存分配是一种类型化操作:new为特定类型分配内存,并在新分配的内存中构造该类型的一个对象.new表达式自己主动执行合适的构造函数来初始化每一个动态分配的类类型对象. new基于每一个对象分配内存的事实可能会对某些类强加不可接受的执行时开销,这种类可能须要使用用户级的类类型对象分配能够更快一些. 这种类使用的通用策略是,预先分配用于创建新对象的内存,须要时在预先分配的内存中构造每一个新对象. 另外一些类希望按最小尺寸为自己的数据成员分配须要的内…
第12章 类和动态内存分配 1.不能在类声明中初始化静态成员变量,这是因为声明描述了如何分配内存,但并不分配内存.可以在类声明之外使用单独的语句进行初始化,这是因为静态类成员是单独存储的,而不是对象的组成部分.注意:静态成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或枚举型const,则可以在类声明中初始化. 2.当使用一个对象来初始化另一个新建对象时,编译器将自动生成一个复制构造函数,因为它创建对象的一个副本.复制构造函数的…
第12章 类和动态内存分配 1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形或枚举型const,则可以在类声明中初始化. P426-P427类静态成员的声明和初始化 //strnbad.h class StringBad { private: static int num_strings; - }; //strnbad.cpp int StringBad::num_strings = 0; 不能在类声明中初始化静态…
前言 该读书笔记用于记录在学习<深入理解Java虚拟机--JVM高级特性与最佳实践>一书中的一些重要知识点,对其中的部分内容进行归纳,或者是对其中不明白的地方做一些注释.主要是方便之后进行复习. 目录 <深入java虚拟机>读书笔记之Java内存区域 垃圾收集器与内存分配策略 哪些内存需要垃圾回收 在上一节中有提到在运行时数据区域包括:堆.虚拟机栈.本地方法栈.程序计数器.方法区(JDK1.7及之前).元空间(JDK1.8及之后).在这些区域中,程序计数器占用内存极小,可以忽略:栈…
JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380620 3.5 经典垃圾收集器 3.5.1 Serial收集器 这个收集器是一个单线程工作的收集器,但它的单线程的意义并不仅仅是说明他只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要对的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束. 目前已经老无可用,但有着优于其他收…
内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你这一切. 线性区 一个可执行程序,是经过编译器处理后的遵守一定规则的数据.符号表和指令序列的组合,当linux加载一个可执行程序的时候,会为其创建一个新的进程,其对应的进程描述符task_struct中会保存许多资源的描述符,其中的mm_struct就是这个进程的内存描述符,用来管理该进程拥有的所有…
void*指针 void关键字表示“空类型”的概念.但是,这里的“空类型”不表示“任意类型”,而是表示不存在的意思,也就是说C/C++不允许你写语句void a,不存在类型为void的东西. void*表示“空类型指针”,与void不同,void*表示“任意类型的指针”或表示“该指针与一地址值相关,但是不清楚在此地址上的对象的类型”. 类型转换 C风格转换: int i; double d; i = (int) d; //或 i = int (d); C风格转换在C++中是适用的.但是C++也提…
delphi 精要-读书笔记(内存分配释放)     1.内存分为三个区域:全局变量区,栈区,堆区 全局变量区:专门存放全局变量 栈区:分配在栈上的变量可被栈管理器自动释放 堆区:堆上的变量内存必须人工去释放 2.指针类变量 指针类的变量在声明为全局变量时被初始化为空值,在声明为局部变量时则初始化为一个随机数,对于指针类型一般要使用一些代码来完成内存分配 3.动态分配内存的函数和过程 procedure GetMem(Var P: Pointer; Size: Integer); 分配大小为Si…
Redis的高效可以说是轻量级的epoll模型和基于内存的读写共同组成的,关于epoll对于以前的select或者poll的性能优势这里不做介绍,本篇主要介绍领一个重点,Redis的内存分配原理. 获取内存信息命令:info memory used_memory: Redis分配器分配的内存总量,就是内部存储的所有数据内存占用量. used_memory_human: 以可读的格式返回used_memory. used_memory_rss: 以操作系统同的角度显示Redis进程占用的物理内存总…
二 垃圾收集器与内存分配策略 1 JVM中哪些内存需要回收?     JVM垃圾回收主要关注的是Java堆和方法区这两个区域:而程序计数器.虚拟机栈.本地方法栈这3个区域随线程而生,随线程而灭,随着方法结束或者线程结束内存自然跟随着回收了,因此不需要过多考虑内存分配和回收的问题.   2 判断对象是否存活的算法     (1)引用计数算法             基本思路:给对象添加一个引用计数器,每当有一个地方引用它,计数器值加1:当引用失效时,计数器减1:任何时刻计数器为0的对象就是不可能再…
1 概述 说起垃圾收集( Garbage Collection , GC ) ,大部分人都把这项技术当做 Java 语言的伴生产物.事实上, GC 的历史远远比 Java 久远,1960 年诞生于 MIT 的 Lisp 是第一门真正使用内存动态分配和垃圾收集技术的语言.当 Lisp 还在胚胎时期时,人们就在思考 GC 需要完成的三件事情: 哪些内存需要回收? 什么时候回收? 如何回收? 经过半个世纪的发展,内存的动态分配与内存回收技术已经相当成熟,一切看起来都进入了“自动化”时代,那为什么我们还…
要实现虚拟机,其实人们主要考虑完成三件事情: 第一,哪些内存需要回收: 第二,什么时候回收: 第三,如何回收. 第二节,对象已死吗    垃圾收集其实主要是针对java堆里面的数据来说的,传统的垃圾收集方法主要是基于引用计数算法,比如windows里面的com或者是actionscript3里面的flash player,以及python语言,但是引用计数算法无法解决对象之间互相影响的问题.所以Java语言没有选用这种方式.    现在主流的商用语言,比如java,c#,都是采用可达性分析的算法…
目录 判断对象是否死亡 引用计数器算法 可达性分析算法 各种引用 回收方法区 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 HotSpot算法实现 枚举根节点 GC停顿(Stop The World) 安全点 垃圾收集器 Serial 收集器 ParNew 收集器 Parallel Scanvenge 收集器 CMS 收集器 G1 收集器 新生代.老年代 和 永久代(元空间) 新生代 老年代 永久代(元空间) Minor GC.Major GC 和 Full GC 何时执…
1. 概述 1) GC的历史比Java久远 2) GC需要完成的三件事: | 哪些内存需要回收 | 什么时候回收 | 如何回收 3) Java内存运行时区域各个部分: | Java虚拟机栈.计数器.本地方法栈随线程而生,随线程而灭,不需要考虑太多问题,因为方法的结束或者线程结束时,内存自然就回收了 | Java堆和方法区只有在运行时才知道需要的内存,分配和回收都是动态的,垃圾收集器所关注的是这部分内存 2. 对象已死吗? 1) 引用计数算法(Reference Counting) | 思路: 给…
在本篇中,作者大量篇幅介绍了当时较为流行的垃圾回收器,但现在Java 14都发布了,垃圾收集器也是有了很大的进步和发展,因此在此就不再对垃圾收集器进行详细的研究.但其基本的算法思想还是值得我们参考学习的. 概述 第一篇笔记Java内存区域与内存溢出异常中讲到了,Java的内存划分可以分为由所有线程共享的Java堆和方法区,以及每个线程之间相互独立的程序计数器.本地方法栈.虚拟机栈.其中每个线程相互独立的部分,并不会给垃圾回收造成困难.因为随着方法.线程的结束,内存自然就释放了.因此我们垃圾收集关…
写在前面 本节常见面试题: 如何判断对象是否死亡(两种方法). 简单的介绍一下强引用.软引用.弱引用.虚引用(虚引用与软引用和弱引用的区别.使用软引用能带来的好处). 如何判断一个常量是废弃常量 如何判断一个类是无用的类 垃圾收集有哪些算法,各自的特点? HotSpot为什么要分为新生代和老年代? 常见的垃圾回收器有那些? 介绍一下CMS,G1收集器. Minor Gc和Full GC 有什么不同呢? 名词解释: 一.新生代.老年代:    转自https://www.cnblogs.com/E…
内核版本:linux-2.6.11 伙伴系统 伙伴系统是linux用于满足对不同大小块物理内存分配和释放请求的解决方案. 内存管理区 linux将物理内存分成三个内存管理区,分别为ZONE_DMA ZONE_NORMAL ZONE_HIGHMEM,并使用三个管理区描述符管理这三个ZONE. 管理区描述符里,有一个元素数为11的free_area数组,分别对应1.2.4.8.16.....不同块的大小,其中的每个元素的类型都是一个名为free_area的结构体,代码位置mm/mmzone.h st…
1.C函数库提供了两个函数,malloc和free,分别用于执行动态内存分配和释放,这些函数维护一个可用内存池. void *malloc(size_t size);//返回指向分配的内存块起始位置的指针.分配的是一块连续内存.分配单位:字节 void free(void *point); 另外 void *calloc(size_t num_elements,size_t element_size);//分配内存并初始化为0 void realloc(void *ptr, size_t new…
垃圾收集 垃圾收集(Garbage Collection,GC),垃圾收集需要完成的三件事情. 哪些对象需要回收 什么时候回收 如何回收 如何确定对象已死(即不可能在被任何途径引用的对象) 引用计数算法 给每一个对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一:当引用失效时,计数器值就减一:计数器值为0的对象就是表示没有在被使用的. 引用计数算法的实现简单,判定效率也比较高,大部分情况下都是一个不错的算法. Java语言中没有采用该算法来管理内存,最主要的原因是该算法没法解决对象…
  Unit 10 Memory Addressing and Allocation 内存地址及分配 学习目标: A. 虚拟地址与物理地 B. 调整内存地址分配 C. 解析内存溢出    10.1 Overview of memory addressing 内存地址概述                 A. 虚拟地址空间         a. 每个进程都有自己线性连续的地址空间         b. 地址空间范围从0到最大地址空间值:           X86: 2^32=4G        …