zoukankan      html  css  js  c++  java
  • 前端中堆和栈的概念

    !!!内容整理自各大博客+理解!!!

    内存中堆和栈概念

    • 栈:先进后出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

    • 堆:队列优先,先进先出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。

    堆与栈区别

    堆与栈实际上是操作系统对进程占用的内存空间的两种管理方式,主要有如下几种区别: (1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏

    (2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小。理论上,程序员可申请的堆大小为虚拟内存的大小,进程栈的大小 64bits 的 Windows 默认 1MB,64bits 的 Linux 默认 10MB;

    (3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。

    (4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进行释放,无需我们手工实现。

    (5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。

    (6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。

    从以上可以看到,堆和栈相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片,并且可能引发用户态和核心态的切换,效率较低。栈相比于堆,在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。虽然栈有众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,主要还是用堆。

    无论是堆还是栈,在内存使用时都要防止非法越界,越界导致的非法内存访问可能会摧毁程序的堆、栈数据,轻则导致程序运行处于不确定状态,获取不到预期结果,重则导致程序异常崩溃,这些都是我们编程时与内存打交道时应该注意的问题。

    数据结构中的堆和栈

    这里不做讨论,其他资料已经写的很明白了

    与前端相关的内容

    JavaScript的数据类型有两大类

    基本类型

    包含null、undefined、Number、String、Boolean,ES6还多了一种Symbol

    基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。

    引用型

    即Object ,是存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。

    概念闲扯

    讲到了堆栈内存那么自然就会牵扯到了闭包、浅拷贝、深拷贝然后就会扯到call、bind、apply

    先来扯一下浅拷贝和深拷贝

    首先!!!!记得只有引用类型才有浅拷贝深拷贝这么 一说,基本数据类型雨女无瓜

    最常用的深拷贝:序列法和反序列法

    // 序列化反序列化法
    function deepClone(obj) {
       return JSON.parse(JSON.stringify(obj))
    }

    在我的面试笔记里,还有更详细的方法,转载自一个博客大佬,真可谓把深拷贝浅拷贝完全剖析

    以下为该大佬地址

    https://www.jianshu.com/p/b08bc61714c7

    再来扯一下闭包

    闭包我个人的理解就是他是一个函数,可以访问别人作用域内变量的函数

    闭包需要理解以下案例

    var name = "The Window";
    var object = {
      name: "My Object",
      getNameFunc: function() {
        return function() {
          return this.name;
        };
      }
    };
    alert(object.getNameFunc()()); //The Window
    ​
    var name = "The Window";
    var object = {
      name: "My Object",
      getNameFunc: function() {
        var that = this;
        return function() {
          return that.name;
        };
      }
    };
    alert(object.getNameFunc()()); //My Object
    ​
    function fun(n, o) {
      console.log(o);
      return {
        fun: function(m) {
          return fun(m, n);
        }
      };
    }
    var a = fun(0);
    a.fun(1);
    a.fun(2);
    a.fun(3); //undefined,?,?,?
    var b = fun(0)
      .fun(1)
      .fun(2)
      .fun(3); //undefined,?,?,?
    var c = fun(0).fun(1);
    c.fun(2);
    c.fun(3); //undefined,?,?,?
    ​
    

      

    call bind apply 引用大佬文章,每次忘记都看一遍!舒服

    JS基础-面试官想知道你有多理解call,apply,bind?[不看后悔系列]

    https://juejin.im/post/5d469e0851882544b85c32ef

  • 相关阅读:
    Python-http请求
    MacOs Big Sur 11.0.1 安装python报错
    linux 根据时间删除某个目录下的文件
    记一次文件上传遇到的坑(文件名|文件格式乱码)
    json_schema参数校验
    K8s
    python实时视频流播放
    pycharm永久激活
    客户端ajax请求为实现Token验证添加headers后导致正常请求变为options跨域请求解决方法
    webstorm修改文件,webpack-dev-server及roadhog不会自动编译刷新
  • 原文地址:https://www.cnblogs.com/liuarui/p/11321441.html
Copyright © 2011-2022 走看看