堆&栈

堆(heap) 和 栈(stack) 都是计算机内存中的存储区域,它们的主要区别在于它们的内存管理方式和使用方式。

堆是动态分配的内存区域,它的大小不固定。比如Go中使用make()分配的引用类型:slice、map...

在堆中,我们可以自由地分配和释放内存空间,但是需要手动管理内存。堆中的内存通常用于存储动态分配的数据结构,如链表、树和图等。

  1. 手动管理(C、C++)
  2. 自带GC的语言会通过一些GC算法进行扫描、清理来自动管理(Java、Go、php)

后进先出LIFO(Last-In-First-Out)的数据结构 

栈是一种线性的数据结构,它具有后进先出(LIFO)的特性。栈中存储的数据以栈帧(Stack Frame)的形式存在,每个栈帧对应一个函数的调用。栈帧包含了函数的局部变量、函数参数、返回地址等信息。当一个函数被调用时,其对应的栈帧被压入栈中;当函数执行完毕后,栈帧被弹出。栈的大小是固定的,由操作系统或编译器预先分配。

栈是一种静态分配的内存区域,它的大小固定。在栈中,数据按照一定的规则存储和访问,通常采用先进后出的方式。

栈中的内存空间由系统自动管理,程序员不能手动分配和释放。栈主要用于存储函数调用时的局部变量和函数调用的返回地址。

栈上的变量比较高效,但是存储空间有限;堆上的变量可以动态地分配和释放内存,但是需要手动管理它们的生命周期,比较复杂。

栈是一种连续的内存空间,数据存储在栈中时,可以通过指针直接访问,访问速度比较快。而堆是一种不连续的内存空间,数据存储在堆中时,需要通过指针间接访问,访问速度相对较慢。

栈的分配和释放是由系统自动完成的,而堆的分配和释放需要程序员手动管理,因此栈的效率也更高。

PS:

内存泄漏

堆和栈都是内存区域,如果程序员没有及时释放堆上的内存,就会导致内存泄漏。内存泄漏会导致程序的性能下降和崩溃等问题。

溢出

栈的大小是固定的,如果程序使用了过多的栈空间,就会导致栈溢出。栈溢出会导致程序崩溃。

线程安全

堆和栈都是多线程共享的资源,因此需要注意线程安全问题。在多线程环境下,需要保证对堆和栈的访问是同步的。

递归

递归是一种常见的算法,它使用函数调用自身来解决问题。递归使用了栈的特性,每次递归调用都会在栈上创建一个新的函数栈帧。因此,在使用递归算法时,需要注意栈的大小和效率问题。

 


 

堆内存存储的数据大小在编译时未知或可能发生变化,也就是只有在程序运行时才能确定数据的大小。

比如,字符串类型的数据在编译时大小是未知的,且运行时大小可能发生变化,因此其必须存储在堆上。

当向堆上放入数据时,操作系统会先找到一块足够大的内存空间,将其标记为已使用,并返回一个指向该空间地址的指针,这个过程称作在堆上分配内存
数据入栈比在堆上分配内存的速度要快。入栈时,操作系统无须为存储新数据去搜索内存空间,其位置总是在栈顶。与之相比,在堆上分配内存需要做更多的工作。

因此,访问栈上数据比访问堆上数据的速度要快,访问栈上数据只需要从栈顶获取,而访问堆上数据需要通过指针搜索内存地址。

posted @ 2019-07-11 10:01  GJH-  阅读(96)  评论(0)    收藏  举报