当前位置: 首页 > news >正文

你了解堆和栈的由来吗?

人们提出内存中堆和栈这两个概念,肯定是要解决当时所遇到的问题,不会为了提出概念而提概念。堆和栈都是为了解决一些问题而发展出来的结果,并没有任何的高深之处。

要搞懂堆和栈的概念是如何来的,就需要从计算机诞生时说起了。

在冯诺依曼提出冯诺依曼计算机时,那是只有存储器,没有将存储器进一步划分。在编程时,整个内存空间任你使用,随便写,整个地址空间,每一个比特都是全局变量。

但时间久后,人们发现,这样写出来的代码真的很难维护、难以让人理解,写出来的代码都是面条代码。

后来,为了解决面条代码的问题,ALGOL提出了结构化编程。每个模块都使用begin和end进行包裹,包裹的部分使用局部变量,不能引用全局变量。

这时,科学家们又遇到了新的问题,在包裹的部分,如何才能实现局部变量呢?

当进入到每个模块时,为这个块单独开辟一块内存空间,。块空间是可以进行嵌套,比如A函数调用B函数,B函数调用C函数。这种嵌套有个特点,最后执行的块,一定是最先执行完成,最先释放空间,然后依次执行和释放。你会发现这就是我们现在所使用的栈,后进先出,即Last-In-First-Out数据结构。

这就是栈的由来,也是结构化编程的结果。

栈最早是体现在计算伯努利数的程序中,由程序员师姐ada编写,大致思路就是从仓库中获得数据,然后计算,然后将结果返回仓库。

结构化编程在上世纪60~70年代很流行,也逐渐被大众所接受,但是又带来了新的问题,这种大量的Push和Pop操作,很容易影响程序执行效率。

为了提高程序执行效率,DEC率先在CPU中增加了四条指令,分别是Push、Pop、PushJ、PopJ;后来出现的CPU,几乎都是遵照了这种范式,一直延续到今天。

下面再来说说堆

我们知道,最早的高级语言是Fortran,这门语言现在还在TIOBE排行榜前十的位置,还是很受欢迎的。早期的Fortran,必须在内存中定义好维度和长度,用今天的话来讲,就是在编译时使用静态变量将空间分配好,不支持在运行时进行动态分配。

如果你今天使用这种语言进行开发,不知道你会换多少个键盘和鼠标。我想你一定会疯掉的,这是什么垃圾玩意。当时的开发人员当然也不爽,严重影响到开发效率。

为了解决这一问题,在上世纪60年代初,BCPL语言首次引入了堆的概念,提供GETBLK和FREEBLK两个函数,用于动态申请内存空间,终于不用在代码里将数据定死了。

在到后来的C语言,就是我们都使用过的malloc和free函数。

这就是堆,为了能让你在运行时才决定内存大小的分配,而不必在编译时就将大小定死。堆并不能准确指代什么,而是一种泛指,泛指操作系统给你一块内存空间存放你任意的东西,不要与数据结构中的堆混合了。

堆和栈是不同的,大多数语言栈上的数据大小在编译期就必须要确定的。当你在类或函数中定义变量时,就是在使用栈;当你使用malloc或new时,就是在使用堆。

我上面说的堆和栈只是一些概念,仅供了解,当你具体在使用堆和栈时,肯定还会有很多细节之处。比如。栈的长度能无限大吗?栈的大小由什么决定?在堆里频繁申请和释放内存,如何减少内存窟窿?如何提高效率?每次malloc后,又要free,这一过程不仅繁琐而且又不安全,有没有在程序运行时自动对内存进行申请和释放(也就是现在的GC)。

如果你对这些基本概念进行理解后,在去理解这些细节就很简单了,没有你想象中的那么难。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • JavaScript异步简介|Promise快速入门
  • 用python创建极坐标平面
  • 住宅代理和数据中心代理:指纹浏览器用哪个更安全?
  • 使用 LinkedList 实现一个高效的缓存系统
  • easyexcel使用教程--导入导出简单案例
  • 第十二章:设置pod和容器权限-保障集群内节点和⽹络安全
  • “微软蓝屏”事件敲响网络安全的警钟
  • C++(2)(数据的共享与保护)
  • Go语言入门
  • Linux安全与高级应用(四)深入探索MySQL数据库:安装、管理与安全实践
  • Journyx项目管理软件 soap_cgi.pyc XXE漏洞复现
  • 【限流与Sentinel超详细分析】
  • 4.8.双向循环神经网络
  • 【C++综合项目】——基于Boost库的搜索引擎(手把手讲解,小白一看就会!!)
  • 前端web开发HTML+CSS3+移动web(0基础,超详细)——第4天
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Angularjs之国际化
  • Bootstrap JS插件Alert源码分析
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • k8s如何管理Pod
  • MD5加密原理解析及OC版原理实现
  • pdf文件如何在线转换为jpg图片
  • React的组件模式
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • STAR法则
  • 程序员最讨厌的9句话,你可有补充?
  • 订阅Forge Viewer所有的事件
  • 码农张的Bug人生 - 初来乍到
  • 面试总结JavaScript篇
  • 什么是Javascript函数节流?
  • 算法---两个栈实现一个队列
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 赢得Docker挑战最佳实践
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • "无招胜有招"nbsp;史上最全的互…
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (52)只出现一次的数字III
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束
  • (笔试题)分解质因式
  • (十六)Flask之蓝图
  • (十三)MipMap
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (新)网络工程师考点串讲与真题详解
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET 使用 XPath 来读写 XML 文件