• 关于值类型、引用类型以及“栈”跟“堆”的关系——转载自菜鸟教程


    值类型,声明一个值类型的时候,是在“栈”中开辟一个内存空间来存放对应的值,当值类型的值发生改变的时候,则直接修改该内存空间所保存的值。例:

    int n1 = 5;
    int n2 = n1;
    Console.WriteLine(n1 + "  "+ n2);    // 5  5
    n2 = 7;
    Console.WriteLine(n1 + "  " + n2)    // 5  7

    这里首先在“栈”中开辟一个内存空间用来保存 n1 的值 5,接着再在“栈”中开辟一个新的内存空间用来保存 n2 的值 5,所以显示出来的结果是 5 5。然后将 n2 在“栈”中对应的内存空间保存的值修改成 7,故显示出来的结果是 5 7。

    引用类型,声明一个引用类型的时候,首先是在“堆”中开辟一个内存空间来存放对应的值,然后在“栈”中开辟一个内存空间用于保存在“堆”中开辟的内存空间的地址。当系统调用引用类型的时候,首先去“栈”中获取到地址,然后根据地址在“堆”中找到对应的内存空间来获取到对应值。像数组这样的引用类型

    string[] a1 = new string[]{ "a" , "b" , "c" };
    string[] a2 = a1;
    for(int i = 0; i < a2.Length; i++)
    {
        Console.Write(a2[i] + " ");    //a b c
    }
    a1[2] = "d";
    Console.WriteLine();            //换行
    for(int i = 0; i < a2.Length; i++)
    {
        Console.Write(a2[i] + " ");    //a b d
    }
    Console.WriteLine();

    这里首先是在“堆”中开辟一个内存空间(假设:0X55)用来保存数组a1的值,然后在“栈”中开辟一个内存空间(a1)用于保存地址 0X55。当将 a1 赋给 a2 时,是将地址赋给 a2,即在“栈”中开辟一个内存空间(a2)用于保存地址 0X55,所以输出 a2 的值是 a b c。当将 a1[2]修改成”d”的时候,修改的是“堆”中 0X55 内存空间保存的值,因为 a2 的地址和 a1 的地址一样,所以输出结果是 a b d。

    而 string 是一个特殊的引用类型,先看下面代码:

    string a = "123";
    string b = a; 
    Console.WriteLine(a+" "+b);  //123 123
    string b = "456";
    Console.WriteLine(a+" "+b);  //123 456

    和数组类似的,这里首先在“堆”中开辟一个内存空间(假设:0X88)用来保存 a 的值 123,然后在“栈”中开辟一个内存空间(a)用于保存地址 0X88。

    和数组不同的是,当将 a 赋给 b 的时候,首先是在“堆”中开辟一个新的内存空间(假设:0X101)用于保存值 123,然后在“栈”中开辟一个内存空间(b)用于保存地址 0X101,所以输出的结果是 123 123。

    当修改 b 值时,并不是修改“堆”中 0X101 内存空间的值,而是在“堆”中重新开辟一个新的内存空间(假设:0X210)用于保存 b 修改后的值,然后将 b 在“栈”中对应的内存空间的所保存的地址修改成 0X210,所以输出的结果是 123 456。而“堆”中的 0X101 内存空间将在下次的垃圾回收中被回收利用。

  • 相关阅读:
    凸透镜和凹透镜为什么分别对光有会聚作用和发散作用
    平面镜成像
    行政 申论 大纲
    专业科 大纲
    linux command --- terminal common commands
    3D VR卡镜的使用方法
    Structure From Motion(二维运动图像中的三维重建)
    双目摄像机
    对比手机SLAM和机器人SLAM
    3D indoor map positioning with a smartphone image
  • 原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/10670650.html
Copyright © 2020-2023  润新知