博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基础才是重中之重~理解内存中的栈和堆
阅读量:6278 次
发布时间:2019-06-22

本文共 1315 字,大约阅读时间需要 4 分钟。

.NET中使用stack(栈)和heap(堆)两种结构在内存中存储数据,今天咱们就来说说这两个结构

  1. Value Types,值类型
          在C#中,值类型继承自System.ValueType的,它们分别是
          Bool,   byte ,  char, decimal, double, enu, float, int, long, sbyte, short, struct, uint, ulong, ushort
  2. Reference Types 引用类型
       
    引用类型包括所有的从System.Object继承下来的类型,它们分别是
           class, interface, delegate, object,string,其中string是一种特殊的引用类型,之后的文章中我会单独说它,.net中的gc(垃圾回收)主要是回收heap中的内存。
  3. 指针:在C#中它已经被遗忘,但不能不说,因为引用类型在内在中事实上是以指针的形式存储在Stack上的,而它的数据内容是在Heap上,也就是上引用类型其实是在stack上做了一个地址的引用。

Stack是自我维护的,意味着基本上不需要我们手动进行内存管理,它有自己的内存管理体系,对于window来说最高是1M,而.net最大只能用256K没有记错的话,如果超出这个范围就会出现溢出。 而heap则是我们建立object对象所存储的地方,它可以由我们自己用GC去回收也可以由.net自己去回收。

对于在教科书上的一个例子,我要说一下,就是斐波那切数列问题,一般书上都是用递归写的,这对于程序员的影响事实上是很大的,如果程序员用普通的递归写这个算法,那你的服务没准什么时候就挂了,原因是内存出现stack溢出的现象,具体的原因用“老赵”同志写了段话非常有代表性:它把普通递归改写成了尾递归解决了这个问题。

int FactorialTailRecursion(int n, int acc) {
if (n == 0) return acc; return FactorialTailRecursion(n - 1, acc * n); //变量仍然对程序有影响,所以编译器会一次一次堆累它使用的内存 }

改成尾递归之后:

int FactorialLoopOptimized(int n, int acc) {
while (true) {
if (n == 0) return acc; acc *= n; n--; } }

方法之前所积累下的各种状态对于递归调用结果已经没有任何意义,因此完全可以把本次方法中留在堆栈中的数据完全清除,把空间让给最后的递归调用。这样 的优化便使得递归不会在调用堆栈上产生堆积,意味着即时是“无限”递归也不会让堆栈溢出”。这其实才是尾递归的“正统”优化方式,那么我们先暂时忘记之前 的“循环优化”,从最简单的示例中查看这样的优化是如何进行的。

在这里,感谢老赵同志对基础的透彻讲解。

转载于:https://www.cnblogs.com/lori/archive/2012/02/10/2346207.html

你可能感兴趣的文章
简单易懂的谈谈 javascript 中的继承
查看>>
多线程基础知识
查看>>
iOS汇编基础(四)指针和macho文件
查看>>
Laravel 技巧锦集
查看>>
Android 使用 ViewPager+RecyclerView+SmartRefreshLayout 实现顶部图片下拉视差效果
查看>>
Flutter之基础Widget
查看>>
写给0-3岁产品经理的12封信(第08篇)——产品运营能力
查看>>
ArcGIS Engine 符号自动化配置工具实现
查看>>
小程序 · 跳转带参数写法,兼容url的出错
查看>>
flutter error
查看>>
Flask框架从入门到精通之模型数据库配置(十一)
查看>>
10年重新出发
查看>>
2019年-年终总结
查看>>
聊聊elasticsearch的RoutingService
查看>>
让人抓头的Java并发(一) 轻松认识多线程
查看>>
从源码剖析useState的执行过程
查看>>
地包天如何矫正?
查看>>
中间件
查看>>
Android SharedPreferences
查看>>
css面试题
查看>>