在计算机领域,堆栈是一个不容忽视的概念,但是很多人甚至是计算机专业的人也没有明确堆栈其实是两种数据结构。
堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。
要点:
堆:顺序随意
栈:后进先出(Last-In/First-Out)
值类型总是在内存中占用一个预定义的字节数(例如,int类型占4个字节,而string类型占用的字节数会根据字符串的长度不同而不同),当声明一个值类型变量时,会在栈中分配适当大小的内存(除了引用类型的值类型成员外,如类的int字段),内存中的这个空间用来存储变量所含的值。.NET维护一个栈指针,它包含栈中下一个可用内存空间的地址。当一个变量离开作用域时,栈指针向下移动被释放变量所占用的字节数,所以它仍指向下一个可用地址。
引用变量也利用栈,但这时栈包含的只是对另一个内存位置的引用,而不是实际值。这个位置是托管堆中的一个地址。和栈一样,它也维护一个指针,包含堆中下一个可用内存空间的地址。但是,堆不是先入后出的,因为对对象的引用可在我们的程序中传递(例如,作为参数传递给方法调用),堆中的对象不会在程序的一个预定点离开作用域。为了在不使用在堆中分配的内存时将它释放,.NET定期执行垃圾收集。垃圾收集器递归地检查应用程序中所有的对象引用。引用不再有效的对象使用的内存无法从程序中访问,该内存就可以回收。
引用类型包含一个指针,指向堆中存储对象本身的位置。因为引用类型只包含引用,不包含实际的值,对方法体内参数所做的任何修改都将影响传递给方法调用的引用类型的变量。
使用基于CLR的语言编译器开发的代码称为托管代码。
托管堆是CLR中自动内存管理的基础。初始化新进程时,运行时会为进程保留一个连续的地址空间区域。这个保留的地址空间被称为托管堆。托管堆维护着一个指针,用它指向将在堆中分配的下一个对象的地址。最初,该指针设置为指向托管堆的基址。
谢谢