by ref vs. by val,变量 vs. 数组 [重复]

Posted

技术标签:

【中文标题】by ref vs. by val,变量 vs. 数组 [重复]【英文标题】:by ref vs. by val, variable vs. array [duplicate] 【发布时间】:2017-08-10 16:00:20 【问题描述】:

按 val 变量:

static void Main(string[] args)

    int i = 3;
    method1(i);
    Console.WriteLine(i);
    Console.ReadLine();

static void method1(int z)

    z *= 2;

输出为 3,因为 method1 没有更改 Main 中的变量。

参考变量:

static void Main(string[] args)

    int i = 3;
    method1(ref i);
    Console.WriteLine(i);
    Console.ReadLine();

static void method1(ref int z)

    z *= 2;

输出为 6,因为 method1 更改了 Main 中的变量。

按 val 排列:

class Program

    static void Main(string[] args)
    
        int[] i =  13, 1, 5 ;
        method1(i);
        Console.WriteLine(String.Join(",",i));
        Console.ReadLine();
    
    static void method1(int[] z)
    
        for(int m=0; m<z.Length;m++)
        
            z[m] *= 2;
        
    

输出为 26、2、10。

引用数组:

class Program

    static void Main(string[] args)
    
        int[] i =  13, 1, 5 ;
        method1(ref i);
        Console.WriteLine(String.Join(",",i));
        Console.ReadLine();
    
    static void method1(ref int[] z)
    
        for(int m=0; m<z.Length;m++)
        
            z[m] *= 2;
        
    

输出又是 26、2、10。

结论: 变量可以通过值或引用传递, 与只能通过引用传递的数组相反。 这是正确的吗? 如果不是 - method1(ref int[] z) 和 method1(int[] z) 有什么区别?我们预计什么时候会得到不同的结果?

【问题讨论】:

尝试在方法中执行z = new int[10]; 之类的操作,您会看到 有引用类型和值类型。然后是按值传递按引用传递。现在将这些相乘得到 4 个组合。 :) 您可能会感到困惑的是,您在这 4 种情况下都传递了一个 变量。第一个变量的类型为int(值类型),第二个变量的类型为int[](引用类型)。因此,在第一种情况下,您传递的是 int 变量的值(一个数字),然后是对 int 变量的引用(它允许您更改原始变量的值)。在第三种情况下,您再次传递了 int[] 变量的值(对数组内存中某处的引用) - 这仍然不能让您更改 变量 i,只有数组的内容。 如果您了解 C 指针,您可以将其与具有本地 int 变量并将其作为 1) int (int 值)、2) int* 传递给函数进行比较(指向位于堆栈上的int 值的指针); 在第二种情况下有一个本地 int* 变量并将其作为 3)int*(指向堆上的 int 值的指针)和 4)@ 987654339@(指向本地int*变量的指针)。 【参考方案1】:

当引用类型对象按值传递时,对对象的引用实际上是按值传递的,所以如果在方法实现中更新对新对象的引用,引用将开始指向新的内存地址。

您可以通过稍微修改方法实现来查看结果的差异,以便将即将到来的输入数组初始化为一个新实例,例如:

static void method1(int[] z)

   z = new int[3]; // new instance created and z has reference to it
                   // while calling side still refers to old memory location
                   // which is  13, 1, 5 
   for(int m=0; m<z.Length;m++)
   
        z[m] *= 2;
    

现在,当您调用按值传递方法时,它将仅在本地为此方法修改z,并且外部数组不会受到影响,而如果您通过引用传递它,那么两个数组都会受到更改的影响。

发生的事情是我们通过创建一个新的数组实例将数组z 设置为引用新的内存位置,因此方法中的引用被更新为指向新的内存位置但调用方引用仍然指向到调用方法之前实例化的旧数组。

当您通过引用传递时,这两个变量都将更新为指向新的内存位置。

static void method1(ref int[] z)

   z = new int[3]; // new instance created and z has reference to it
                   // now calling side also refers to new memory location
                   // which is new int[3];
   for(int m=0; m<z.Length;m++)
   
        z[m] *= 2;
    

【讨论】:

谢谢 Ehsan Sajjad!我从您的示例中了解到,在“by val”的情况下,method1 将初始化一个新数组,而在“by ref”的情况下,它将重新初始化现有数组,并且其所有元素都将变为零。对吗? "在 "by ref" 的情况下,它将重新初始化现有数组" -- 不,它将重新分配现有的 变量。现有的 array 不会改变。您不再有任何方法可以引用该现有数组,但如果您在调用 method1 之前将对该数组的引用存储在另一个变量中,您会发现它并没有改变。 不,不会,新数组被创建,旧数组引用丢失,但它在内存中,很快就会被垃圾收集器收集

以上是关于by ref vs. by val,变量 vs. 数组 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Hive : SORT BY vs ORDER BY vs DISTRIBUTE BY vs CLUSTER BY

Hive cluster by vs order by vs sort by

mysql order by -id vs order by id desc

VS2012 Team Explorer 中的“Filter By Solution”按钮在哪里?

GROUP BY vs INSERT IGNORE

Visual studio 2013打开报异常"Exception has been thrown by the target of an invocation"