8, 堆,栈,内存管理
栈: local objects 在离开作用域之后就会被消除.
堆: new MyClass 一直会存在
静态对象: static local object 作用域在当前函数,其生命在整个程序结束后才会结束.
全局对象: Global object 作用域在全局.
new函数的内部实现:
e.g Complex * pc = new Complex(1,2);
分解:
1, void* mem = operator new(sizeof(Complex)); -分配内存 使用molloc实现
2, pc = static_cast<Complex*>(mem); - 转型
3, pc->Complex::Complex(1,2); - 构造函数
delete函数的内部实现:
e.g delete pc;
分解:
1, String::~String(pc); -析构函数
2, operator delete(pc); -释放内存 内部使用free实现
动态分配得到的内存块:
debug:
头尾: cookie (小甜饼干) 4x2
复数 : 8b
最终加起来得到的内存块为 52b
但是在vc下, 每个内存块分配都是16的倍数.
所以,这里需要填补(pad) 得到64
release:
正好是16的倍数.
cookie说明:
cookie的作用是记录整块分配内存的大小.
因为都是16的倍数,所以最后有4个为是空的. 所以最后那位我们可以使用.
当最后一位是1时,说明是系统分配给我们的.
如果我们要把内存还给系统,那么最后一位就会变成0.
vc中动态分配数组
debug:
8*3是数据
32+4是调试相关字符
4*2是cookie
最后的4是数组的大小 保存数据'3'
最后80是要向16对齐.
release:
内存泄露不是我们所以为的内存泄露:
array new 一定要搭配array delete
e.g String* p = new String[3];
delete[] p; -唤起3次析构函数
delete p; -唤起1次析构函数
无论上面哪种方式,都会删除cookie中间的那块内存.
所以问题是出现在里面保存对象是否调用了析构函数.
各自的析构就会负责把自己动态分配的内存删除掉.
所以, 如果数组中的对象不含有指针.所以只用delete也是可以的,也不会造成内存泄露.
疑问:
为什么系统不直接根据 那个'3'字节来将全部对象调用析构? 而是非得要求用户调用delete[]
9,复习String类的实现
strlen取得的长度不含'\0'
在拷贝赋值中, 返回类型尽量使用 MyClass& MyClass::operator=(const MyClass& m2) !
而不是void MyClass::operator=(const MyClass& m2)
使用void在一般情况: m1 = m2 这样的一个赋值上是没有问题的. 但, 当一连串赋值的时候就必须使用返回引用了! ! ! !
这就贯彻了之前说过的 "调用者无需知道函数是使用什么方式传递出去的"
一定要注意 取地址符号&和引用符号&的区分!
10, 拓展补充
static 关键字
静态数据
MyClass{
static int count; //- 无论创造多少个对象, 这个变量只有一份.
static void Set_Count(int cc) { count = cc;}
};
注意: 静态变量 一定要在类外进行定义(我们俗称初始化);
int MyClass::count = 10; //格式一定要注意! 前面的类型一定要写!后面要不要赋值不是必要.
静态函数调用方式:
1,通过对象来调用:
MyClass my;
my.Set_Count(2);
2,通过类名来调用:
MyClass::Set_Count(3);
单例模式:
把构造函数放在private区内. 这样就不能通过普通模式构建对象, 此时再声明一个静态成员函数,用于返回一个实例化对象.
8, 堆,栈,内存管理
栈: local objects 在离开作用域之后就会被消除.
堆: new MyClass 一直会存在
静态对象: static local object 作用域在当前函数,其生命在整个程序结束后才会结束.
全局对象: Global object 作用域在全局.
new函数的内部实现:
e.g Complex * pc = new Complex(1,2);
分解:
1, void* mem = operator new(sizeof(Complex)); -分配内存 使用molloc实现
2, pc = static_cast<Complex*>(mem); - 转型
3, pc->Complex::Complex(1,2); - 构造函数
delete函数的内部实现:
e.g delete pc;
分解:
1, String::~String(pc); -析构函数
2, operator delete(pc); -释放内存 内部使用free实现
动态分配得到的内存块:
debug:
头尾: cookie (小甜饼干) 4x2
复数 : 8b
最终加起来得到的内存块为 52b
但是在vc下, 每个内存块分配都是16的倍数.
所以,这里需要填补(pad) 得到64
release:
正好是16的倍数.
cookie说明:
cookie的作用是记录整块分配内存的大小.
因为都是16的倍数,所以最后有4个为是空的. 所以最后那位我们可以使用.
当最后一位是1时,说明是系统分配给我们的.
如果我们要把内存还给系统,那么最后一位就会变成0.
vc中动态分配数组
debug:
8*3是数据
32+4是调试相关字符
4*2是cookie
最后的4是数组的大小 保存数据'3'
最后80是要向16对齐.
release:
内存泄露不是我们所以为的内存泄露:
array new 一定要搭配array delete
e.g String* p = new String[3];
delete[] p; -唤起3次析构函数
delete p; -唤起1次析构函数
无论上面哪种方式,都会删除cookie中间的那块内存.
所以问题是出现在里面保存对象是否调用了析构函数.
各自的析构就会负责把自己动态分配的内存删除掉.
所以, 如果数组中的对象不含有指针.所以只用delete也是可以的,也不会造成内存泄露.
疑问:
为什么系统不直接根据 那个'3'字节来将全部对象调用析构? 而是非得要求用户调用delete[]
9,复习String类的实现
strlen取得的长度不含'\0'
在拷贝赋值中, 返回类型尽量使用 MyClass& MyClass::operator=(const MyClass& m2) !
而不是void MyClass::operator=(const MyClass& m2)
使用void在一般情况: m1 = m2 这样的一个赋值上是没有问题的. 但, 当一连串赋值的时候就必须使用返回引用了! ! ! !
这就贯彻了之前说过的 "调用者无需知道函数是使用什么方式传递出去的"
一定要注意 取地址符号&和引用符号&的区分!
10, 拓展补充
static 关键字
静态数据
MyClass{
static int count; //- 无论创造多少个对象, 这个变量只有一份.
static void Set_Count(int cc) { count = cc;}
};
注意: 静态变量 一定要在类外进行定义(我们俗称初始化);
int MyClass::count = 10; //格式一定要注意! 前面的类型一定要写!后面要不要赋值不是必要.
静态函数调用方式:
1,通过对象来调用:
MyClass my;
my.Set_Count(2);
2,通过类名来调用:
MyClass::Set_Count(3);
单例模式:
把构造函数放在private区内. 这样就不能通过普通模式构建对象, 此时再声明一个静态成员函数,用于返回一个实例化对象.
- cassandra 堆外内存管理
为什么需要堆外内存呢 单有一些大内存对象的时候,JVM进行垃圾回收时需要收集所有的这些对象的内存也.增加了GC压力.因此需要使用堆外内存. java 分配堆外内存 org.apache.cassand ...
- Java堆外内存管理
Java堆外内存管理 1.JVM可以使用的内存分外2种:堆内存和堆外内存: 堆内存完全由JVM负责分配和释放,如果程序没有缺陷代码导致内存泄露,那么就不会遇到java.lang.OutOfMemo ...
- Java堆外内存之五:堆外内存管理类ByteBuffer
本篇主要讲解如何使用直接内存(堆外内存),并按照下面的步骤进行说明: 相关背景-->读写操作-->关键属性-->读写实践-->扩展-->参考说明 希望对想使用直接内存的朋 ...
- Java 堆内存与栈内存异同(Java Heap Memory vs Stack Memory Difference)
--reference Java Heap Memory vs Stack Memory Difference 在数据结构中,堆和栈可以说是两种最基础的数据结构,而Java中的栈内存空间和堆内存空间有 ...
- Java堆内存与栈内存对比
在数据结构中,堆和栈可以说是两种最基础的数据结构,而Java中的栈内存空间和堆内存空间有什么异同,以及和数据结构中的堆栈有何关系? 一.Java 堆存储空间 堆内存(堆存储空间)会在Java运行时分配 ...
- Linux C 堆内存管理函数malloc()、calloc()、realloc()、free()详解
C 编程中,经常需要操作的内存可分为下面几个类别: 堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等,它们获取的方式都是由编译器自动执行的 堆区(heap):一般 ...
- C++内存管理4-Windows编程中的堆管理(转)
1 引言 在大多数Windows应用程序设计中,都几乎不可避免的要对内存进行操作和管理.在进行大尺寸内存的动态分配时尤其显的重要.本文即主要对内存管理中的堆管理技术进行论述. 堆(Heap)实际是位于 ...
- 内存管理之堆heap
1.什么是堆? 堆(heap)是一种内存管理方式.内存管理对操作系统来说是一件非常复杂的事情,因为首先内存容量很大, 其次就是内存需求在时间和大小块上没有规律(操作系统上运行着几十甚至几百个进程,这些 ...
- C#下内存管理--垃圾收集
章节安排 内存管理简介 垃圾回收机制 性能问题 C#下非托管资源的处理 要强调的几点 References 内存管理简介 对于任何一种编程语言,内存管理都是不得不提很重要的一块内容,但可惜的是目前为止 ...
随机推荐
- jquery无缝向上滚动实现代
<!DOCTYPE html><html><head><style type="text/css">.renav{width:200 ...
- 在Spring-boot中,为@Value注解添加从数据库读取properties支持
一般我们会把常用的属性放在工程的classpath文件夹中,以property,yaml或json的格式进行文件存储,便于Spring-boot在初始化时获取. @Value则是Spring一个非常有 ...
- mysql数据库优化思路
1.设置合适的主键和索引. (1).设置主键和索引的字段尽量不要选取经常修改的字段,同时索引的个数一般不宜超过6个: (2).sql语句中like “%str%” 不支持索引, "str% ...
- 8 包含min函数的栈
0 引言 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数.在该栈中,调用min.push及pop的时间复杂度都是O(). 1 抽象问题具体化 2 具体问题抽象分析 需要解 ...
- 【CF888G】Xor-MST
题目 也不是很知道为什么这道题要和某\(B\)姓算法扯上关系 首先有一个非常显然基于那个\(B\)姓算法的做法,每次启发式合并\(trie\)即可,复杂度是\(O(n\ logn\ loga_i)\) ...
- Linux使用crontab定时执行Python脚本清理日志
Linux中,周期执行的任务一般由crond这个守护进程来处理.cron读取一个或多个配置文件,这些配置文件中包含了命令行及其调用时间.crond的配置文件称为"crontab", ...
- C# 中的三个高级参数 ref
今天在浏览博文时,看到这篇文章:C#中的ref 传进出的到底是什么 ? 在传对象时使用ref的疑问 引用类型就传的就是地址,值类型传的就是值,可是还仍有那么多人迷惑,网上虽然流传着很多ref 的相关文 ...
- 笔记:Python操作sql
python操作mysql步骤: 创建connect连接 conn = connect(host='127.0.0.1', port=3306, user='root', password='1234 ...
- 警告(alert 消息对话框) 如果你不点击“确定”,就不能对网页做任何操作,这个小窗口就是使用alert实现的
警告(alert 消息对话框) 我们在访问网站的时候,有时会突然弹出一个小窗口,上面写着一段提示信息文字.如果你不点击"确定",就不能对网页做任何操作,这个小窗口就是使用alert ...
- 【左偏树】[APIO2012]派遣
题意可真的是有毒 第一眼树形背包可做?(反正我没用树形背包打过,边上巨佬打的背包似乎没拿分) 后来发现可以贪心搞,我们先把一个节点所有的儿子都取进去,之后不行的话再从大的开始拿走就好了 问题就变成了了 ...