zoukankan      html  css  js  c++  java
  • C#---引用类型,值类型和堆栈

    1.值类型(System.ValueType类)和栈(Stack)

    System.ValueType--bool、byte、char、decimal、double、enum、float、int、long、sbyte、short、struct、unit、ulong、ushort。

    栈是编译期间就分配好的内存空间,代码中就栈的大小有明确的定义。栈是连续的内存域,由系统自动分配和维护。

    • 栈保存代码的执行步骤--函数调用返回

      A->B->C->D 函数调用压栈 返回是弹栈D->C->B->A

    •  存放变量-值类型

          值类型不一定被分配到栈上,值类型被声明在一个方法体外并且在一个引用类型中,会在堆上进行分配。(成员变量或属性)

    • 存储空间释放(垃圾回收)

          栈内存无需我们管理,也不受GC管理。栈顶元素使用完毕,立即释放。

    2.引用类型(System.Object)和堆(Heap)

    System.Object---class、interface、delegate、object、string

    堆是程序运行期间动态分配的内存空间,可以根据程序的运行情况确定要分配的堆内存大小。堆是无序的,由用户来控制和释放,若用户不释放,当内存达到一定的特定值时,通过垃圾回收器(GC)回收。

    • 存放对象-引用类型
    • 存储空间释放

       堆则需要GC(Garbage collection:垃圾收集器)清理

    在程序运行的时候,每个线程(Thread)都会维护一个自己的专属线程堆栈。

    指针:

    当一个方法被调用的时候,主线程开始在所属程序集的元数据中,查找被调用方法,然后通过JIT即时编译并把结果(一般是本地CPU指令)放在栈顶。CPU通过总线从栈顶取指令,驱动程序以执行下去。

    3. 栈示例:

    public int AddFive(int pValue)
    {
    int result;
    result = pValue + 5;
    return result;
    }

    方法开始调用时,方法参数在栈上分配 

    方法内部开始执行时,变量result被分配在栈上

    方法执行完毕,而且方法返回后

    栈上的区域被清理。

    4.堆示例

    public class MyInt
    { 
        public int MyValue;
    }
     
    public MyInt AddFive(int pValue)
    {
        MyInt result = new MyInt();
        result.MyValue = pValue + 5;
        return result;
    }

    方法被调用时,参数被分配到栈上

    方法开始执行,由于MyInt是引用类型,result是指向引用类型的指针

    方法执行完毕,栈上内存被清理,但堆中依然存在

    当程序需要更多的堆空间时,GC需要进行垃圾清理工作,暂停所有线程,找出所有不可达到对象,即无被引用的对象,进行清理。并通知栈中的指针重新指向地址排序后的对象。当我们使用引用类型的时候,一般是对指针进行的操作而非引用类型对象本身。但是值类型则操作其本身。

     5.Dictionary<string,int> foreach无法修改值类型取值(MoveNext报错)

    值类型:

    Dictionary<string, int> doc = new Dictionary<string, int>();
    doc.Add("sl", 1);
    doc.Add("xm", 2);
    doc.Add("xl", 3);
     foreach (var item in doc)
    {
        Console.WriteLine(item.Value);
     }

    IL代码:

    .method public hidebysig static void  TestValueType() cil managed
    {
      // 代码大小       106 (0x6a)
      .maxstack  3
      .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32> doc,
               [1] valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,int32> V_1,
               [2] valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,int32> item)
      IL_0000:  nop
      IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::.ctor()
      IL_0006:  stloc.0
      IL_0007:  ldloc.0
      IL_0008:  ldstr      "sl"
      IL_000d:  ldc.i4.1
      IL_000e:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::Add(!0,
                                                                                                                    !1)
      IL_0013:  nop
      IL_0014:  ldloc.0
      IL_0015:  ldstr      "xm"
      IL_001a:  ldc.i4.2
      IL_001b:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::Add(!0,
                                                                                                                    !1)
      IL_0020:  nop
      IL_0021:  ldloc.0
      IL_0022:  ldstr      "xl"
      IL_0027:  ldc.i4.3
      IL_0028:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::Add(!0,
                                                                                                                    !1)
      IL_002d:  nop
      IL_002e:  nop
      IL_002f:  ldloc.0
      IL_0030:  callvirt   instance valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<!0,!1> class [mscorlib]System.Collections.Generic.Dictionary`2<string,int32>::GetEnumerator()
      IL_0035:  stloc.1
      .try
      {
        IL_0036:  br.s       IL_004f
        IL_0038:  ldloca.s   V_1
        IL_003a:  call       instance valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!0,!1> valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,int32>::get_Current()
        IL_003f:  stloc.2
        IL_0040:  nop
        IL_0041:  ldloca.s   item
        IL_0043:  call       instance !1 valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,int32>::get_Value()
        IL_0048:  call       void [mscorlib]System.Console::WriteLine(int32)
        IL_004d:  nop
        IL_004e:  nop
        IL_004f:  ldloca.s   V_1
        IL_0051:  call       instance bool valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,int32>::MoveNext()
        IL_0056:  brtrue.s   IL_0038
        IL_0058:  leave.s    IL_0069
      }  // end .try
      finally
      {
        IL_005a:  ldloca.s   V_1
        IL_005c:  constrained. valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,int32>
        IL_0062:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
        IL_0067:  nop
        IL_0068:  endfinally
      }  // end handler
      IL_0069:  ret
    } // end of method Program::TestValueType

    引用类型:

     Dictionary<string, Student> doc = new Dictionary<string, Student>();
     Student s = new Student();
     s.name = "sl";
     s.point = 1;
     doc.Add("NO1",s);
     Student t = new Student();
     t.name = "xm";
     s.point = 2;
     doc.Add("NO2", t);
     Student st = new Student();
     st.name = "xl";
     st.point = 3;
     doc.Add("NO3", st);
    foreach(var item in doc)
    {
      item.Value.name = "same";
    }

    IL代码:

    .method public hidebysig static void  TestObject() cil managed
    {
      // 代码大小       184 (0xb8)
      .maxstack  3
      .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student> doc,
               [1] class TestDictionaryIL.Program/Student s,
               [2] class TestDictionaryIL.Program/Student t,
               [3] class TestDictionaryIL.Program/Student st,
               [4] valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,class TestDictionaryIL.Program/Student> V_4,
               [5] valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,class TestDictionaryIL.Program/Student> item)
      IL_0000:  nop
      IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::.ctor()
      IL_0006:  stloc.0
      IL_0007:  newobj     instance void TestDictionaryIL.Program/Student::.ctor()
      IL_000c:  stloc.1
      IL_000d:  ldloc.1
      IL_000e:  ldstr      "sl"
      IL_0013:  stfld      string TestDictionaryIL.Program/Student::name
      IL_0018:  ldloc.1
      IL_0019:  ldc.i4.1
      IL_001a:  stfld      int32 TestDictionaryIL.Program/Student::point
      IL_001f:  ldloc.0
      IL_0020:  ldstr      "NO1"
      IL_0025:  ldloc.1
      IL_0026:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::Add(!0,
                                                                                                                                                     !1)
      IL_002b:  nop
      IL_002c:  newobj     instance void TestDictionaryIL.Program/Student::.ctor()
      IL_0031:  stloc.2
      IL_0032:  ldloc.2
      IL_0033:  ldstr      "xm"
      IL_0038:  stfld      string TestDictionaryIL.Program/Student::name
      IL_003d:  ldloc.1
      IL_003e:  ldc.i4.2
      IL_003f:  stfld      int32 TestDictionaryIL.Program/Student::point
      IL_0044:  ldloc.0
      IL_0045:  ldstr      "NO2"
      IL_004a:  ldloc.2
      IL_004b:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::Add(!0,
                                                                                                                                                     !1)
      IL_0050:  nop
      IL_0051:  newobj     instance void TestDictionaryIL.Program/Student::.ctor()
      IL_0056:  stloc.3
      IL_0057:  ldloc.3
      IL_0058:  ldstr      "xl"
      IL_005d:  stfld      string TestDictionaryIL.Program/Student::name
      IL_0062:  ldloc.3
      IL_0063:  ldc.i4.3
      IL_0064:  stfld      int32 TestDictionaryIL.Program/Student::point
      IL_0069:  ldloc.0
      IL_006a:  ldstr      "NO3"
      IL_006f:  ldloc.3
      IL_0070:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::Add(!0,
                                                                                                                                                     !1)
      IL_0075:  nop
      IL_0076:  nop
      IL_0077:  ldloc.0
      IL_0078:  callvirt   instance valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<!0,!1> class [mscorlib]System.Collections.Generic.Dictionary`2<string,class TestDictionaryIL.Program/Student>::GetEnumerator()
      IL_007d:  stloc.s    V_4
      .try
      {
        IL_007f:  br.s       IL_009d
        IL_0081:  ldloca.s   V_4
        IL_0083:  call       instance valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!0,!1> valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,class TestDictionaryIL.Program/Student>::get_Current()
        IL_0088:  stloc.s    item
        IL_008a:  nop
        IL_008b:  ldloca.s   item
        IL_008d:  call       instance !1 valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<string,class TestDictionaryIL.Program/Student>::get_Value()
        IL_0092:  ldstr      "same"
        IL_0097:  stfld      string TestDictionaryIL.Program/Student::name
        IL_009c:  nop
        IL_009d:  ldloca.s   V_4
        IL_009f:  call       instance bool valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,class TestDictionaryIL.Program/Student>::MoveNext()
        IL_00a4:  brtrue.s   IL_0081
        IL_00a6:  leave.s    IL_00b7
      }  // end .try
      finally
      {
        IL_00a8:  ldloca.s   V_4
        IL_00aa:  constrained. valuetype [mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<string,class TestDictionaryIL.Program/Student>
        IL_00b0:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
        IL_00b5:  nop
        IL_00b6:  endfinally
      }  // end handler
      IL_00b7:  ret
    } // end of method Program::TestObject
  • 相关阅读:
    关于JavaScript文档对象
    关于JavaScript浏览器对象
    关于JavaScript事件与函数
    关于JavaScript基础知识
    关于CSS基础知识
    第七章:Hexadecimal, octal, ASCII, UTF8, Unicode, Runes
    没有 Cgroups,就没有 Docker
    Redis 文件事件
    Python 垃圾回收总结
    Docker Bridge 网络原理
  • 原文地址:https://www.cnblogs.com/mbaymax/p/10237337.html
Copyright © 2011-2022 走看看