zoukankan      html  css  js  c++  java
  • 一道题引发的对引用类型的思考

      

    参考资料:

    http://www.cnblogs.com/qguohog/archive/2009/12/26/1632967.html

    http://www.cppblog.com/luyulaile/archive/2011/04/08/143703.aspx

    http://www.cnblogs.com/guowenhui/archive/2011/10/24/2222927.html

    http://www.csharpwin.com/csharpspace/6876r6119.shtml

    从网上看了一道题:

    class Class1  {
           private string str = "Class1.str";
           private int i = 0;
           static void StringConvert(string str)  {
               str = "string being converted.";
           }
           static void StringConvert(Class1 c)  {
               c.str = "string being converted.";
           }
           static void Add(int i)  {
               i++;
           }
           static void AddWithRef(ref int i)  {
               i++;
           }
           static void Main()  {
               int i1 = 10;
               int i2 = 20;
               string str = "str";
               Class1 c = new Class1();
               Add(i1);
               AddWithRef(ref i2);
               Add(c.i);
               StringConvert(str);        
               StringConvert(c);
               Console.WriteLine(i1);
               Console.WriteLine(i2);
               Console.WriteLine(c.i);
               Console.WriteLine(str);
               Console.WriteLine(c.str);
           } 
        }

    出觉得不明白的地方是:

    StringConvert(str);         
    StringConvert(c);

    Console.WriteLine(str);
               Console.WriteLine(c.str);

    这块应该输出什么?

      

       static void StringConvert(string str) 、static void StringConvert(Class1 c) 这两个函数的参数,都是默认按值传递的。

      在我理解感觉跟赋值有点类似:

        string str=str; /* string 是引用类型,继承了 ICloneable接口。实现了深拷贝,所以字符串赋值的时候会重新new一个字符串出来赋给方法参数,

                这个相当于产生一个新的对象,函数体中的操作和Main里穿过来的str参数没有关联,不会改变str的值。*/

        Class1 c = c; /* class是引用类型,引用类型的引用地址放在了栈上,实际的实例对象放在了堆上,赋值的时候是在栈里面复制了Main里面new的c的引用地址,

                它们同时指向了一个堆的地址。所以函数体里对str的操作反映到Main里面new的c.str。 */

    另外:

      

      string跟普通的引用类型不太一样的地方:

    例如:

    • string   str1="abc";  
    • string   str2="abc"

      C# String对象是存放在堆上,而不是堆栈上的。

      字符串驻留的技术:CLR初始化时,会创建一个内部的散列表,其中的键为字符串,值为指向托管堆中字符串的引用。刚开始,散列表为空,JIT编译器编译方法时,会在散列表中查找每一个文本常量字符串,首先会查找"abc"字符串,并且因为没有找到,编译器会在托管堆中构造一个新的指向"abc"的C# String对象引用,然后将"abc"字符串和指向该对象的引用添加到散列表中。

      接着,在散列表中查找第二个"abc",这一次由于找到了该字符串,所以编译器不会执行任何操作,代码中再没有其它的文本常量字符串,编译器的任务完成,代码开始执行。执行时,CLR发现第一个语句需要一个"abc"字符串引用,于是,CLR会在内部的散列表中查找"abc",并且会找到,这样指向先前创建的C# String对象的引用就被保存在变量s1中,执行第二条语句时,CLR会再一次在散列表中查找"abc",并且仍然会找到,指向同一个C# String对象的引用会被保存在变量s2中,到此s1和s2指向了同一个引用。

      str1 = str2; // 字符串继承了ICloneable接口,深拷贝,会创建一个新对象。

      

  • 相关阅读:
    Java实现 LeetCode 653 两数之和 IV
    Java实现 LeetCode 653 两数之和 IV
    Java实现 LeetCode 652 寻找重复的子树(两个map的DFS)
    PHP imageaffine
    PHP image2wbmp
    PHP image2wbmp
    PHP image_type_to_extension
    PHP getimagesizefromstring
    用户选择 | user-select (Basic User Interface)
    用户界面 | CSS User Interface (Basic User Interface)
  • 原文地址:https://www.cnblogs.com/ThinkWorld/p/3308299.html
Copyright © 2011-2022 走看看