栈和堆的区别
1、程序的内存分配方式不同
栈区(stack):编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构的栈。
堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是类似于数据结构的链表。
2、申请方式不同
stack 由系统自动分配,heap 需要程序员自己申请。
C 中用函数 malloc分配空间,用 free 释放,C++用 new 分配,用 delete 释放。
3、申请后系统的响应不同
栈:只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录内存地址的链表,当系统收到程序的申请时,遍历该链表,寻找第一个空间大于所申请的空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的 delete 或 free 语句就能够正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会将多余的那部分重新放入空闲链表中。
4、 申请的大小限制不同
栈:在 windows 下,栈是向低地址扩展的数据结构,是一块连续的内存区域,栈顶的地址和栈的最大容量是系统预先规定好的,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域,这是由于系统是由链表在存储空闲内存地址,自然堆就是不连续的内存区域,且链表的遍历也是从低地址向高地址遍历的,堆得大小受限于计算机系统的有效虚拟内存空间,由此空间,堆获得的空间比较灵活,也比较大。
5、申请的效率不同
栈:栈由系统自动分配,速度快,但是程序员无法控制。
堆:堆是有程序员自己分配,速度较慢,容易产生碎片,不过用起来方便。
6、堆和栈的存储内容不同
栈:在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令的地址,然后函数的各个参数,在大多数的 C 编译器中,参数是从右往左入栈的,当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令。
堆:一般是在堆的头部用一个字节存放堆的大小,具体内容由程序员安排。
在C#中,变量主要分为以下几种类型:
●值类型(Value Types)
●引用类型(Reference Types)
●指针类型(Pointer Types)
值类型(Value Types)主要包括哪些?
顺口溜:整浮布字结枚(实际数据存储栈中,操作系统负责管理分配释放)
●整型数值类型
●浮点型数值类型
●布尔类型(bool)
●字符类型(char)
●结构类型(struct type)
●枚举类型(enum type)
引用类型(Reference Types)主要包括哪些?
顺口溜:对字类接委动数(实际数据存储在堆中,GC负责管理分配释放)
●对象类型(object)
●字符串类型(string)
●类(class)
●接口(interface)
●委托类型(delegate)
●动态类型(dynamic)
●数组类型(array)
C#值类型和引用类型的区别?
1、速度上的区别
值类型存取速度快,引用类型存取速度慢。
2、用途上的区别
值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针或引用。
3、来源上的区别
值类型继承自System.ValueType,引用类型继承自System.Object
4、位置上的区别
值类型的数据存储在内存的栈中,引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地址。
5、类型上的区别
值类型的变量直接存放实际的数据,而引用类型的变量存放的则是数据的地址,即对象的引用。
6、保存位置上的区别
值类型变量直接把变量的值保存在堆栈中,引用类型的变量把实际数据的地址保存在堆栈中,而实际数据则保存在堆中。
C#装箱和拆箱
什么是装箱和拆箱?
装箱:将值类型转化为引用类型的过程。
拆箱:将引用类型转化为值类型的过程。
装箱和拆箱的作用
C#中值类型和引用类型的最终基类都是Object类型(它本身是一个引用类型)。
也就是说,值类型也可以当做引用类型来处理。而这种机制的底层处理就是通过装箱和拆箱的方式来进行,利用装箱和拆箱功能,可通过允许值类型的任何值与Object 类型的值相互转换,将值类型与引用类型链接起来 。
但是装箱和拆箱的过程会有性能的消耗,所以一般情况下我们建议使用泛型。
装箱和拆箱转化的性能问题
相对于简单的赋值而言,装箱和取消装箱过程需要进行大量的计算。 对值类型进行装箱时,必须分配并构造一个新对象。 取消装箱所需的强制转换也需要进行大量的计算,只是程度较轻。
C#如何判断变量是什么类型?
有如下两种方式:
●"追逐时光者".GetType()获取当前实例准确的运行时类型。
●is关键字判断对象变量是否是指定的类型。
dynamic动态类型与object类型的区别
object 类型是.NET 里面 System.Object 的别名,在 C#中所有的类型(预定义、用户定
义、引用类型、值类型)都直接或者间接的继承自 Object。所以我们可以将任何类型的值
用 object 对象来接收;
动态类型(dynamic)在编译时会绕过类型检查,从而在运行时解析。所以动态类型只存
在于编译时,不存在于运行时;
假设我们有下面一个方法:
public class TestDynamicAndObjectType{ public static void ConsoleWrite(string inputArg) { Console.WriteLine(inputArg); } static void Main() { // object 类型演示 object obj = "追逐时光者"; // 编译错误 除非转化为 string 类型 ConsoleWrite(obj);// compile error ConsoleWrite((string)obj); // correct Console.ReadKey(); // dynamic 类型演示 dynamic dyn = "追逐时光者"; ConsoleWrite(dyn); // correct dyn = 1; // 编译时不报错, 运行时会报错 ConsoleWrite(dyn);// Runtime Error Console.ReadKey(); }}