【问题标题】:Passing array elements by ref [duplicate]通过 ref 传递数组元素 [重复]
【发布时间】:2011-10-18 12:31:43
【问题描述】:

可能重复:
C# parameters by reference and .net garbage collection

我正在考虑使用 ref 参数来限制数组的边界检查。例如交换两个元素的代码是:

class Test {
  int[] array;

  private void qSort() {
    ...blah...
    int temp = array[a];
    array[a] = array[b];
    array[b] = temp;
  }
}

它有 4 次访问数组 替代方案是:

class Test {
  int[] array;

  private void qSort() {
  ...blah...
    Swap( ref array[a], ref array[b] );
  }

  static void Swap(ref int a,ref int b) {
    int temp = a;
    a=b;
    GC.Collect();  // suppose this happens
    b=temp;
  }
}

理论上只有 2 次访问数组

让我感到困惑的是,当我通过 ref 传递数组元素时,我不知道究竟会发生什么。如果垃圾收集器启动,在交换函数中执行代码时,将能够移动数组吗?或者数组在通话期间被固定?

请注意,上面的代码是一个简单的测试用例。我想在更复杂的场景中使用它

编辑:正如 BrokenGlass 所指出的,Eric Lippert 在这里C# parameters by reference and .net garbage collection回答了这个问题@

数组不会被固定,GCollector 可以移动它,并将相应地更新任何 ref 到它的元素,它驻留​​在堆栈中

【问题讨论】:

  • 不要尝试过早优化,尤其是如果您对机器的工作原理没有深入了解。恰当的例子:由于拳击,您的第二个版本(使用ref)实际上会比第一个版本慢很多(循环尝试看看)。
  • @Jon,我同意出于性能原因这样做可能没有意义,但它确实提高了可读性......顺便说一句,在这种情况下没有装箱
  • 上述 SO 线程有一个 Eric Lippert 的回答,应该澄清压缩/移动问题
  • @Jon:拳击在哪里?当值类型转换为引用类型时会发生装箱,但这里没有引用类型。
  • @PanosTheof:假设我告诉过你如果下雨,那么街道就会湿。从逻辑上讲,这并不意味着正在下雨! 如果垃圾收集器移动了一块内存,那么存在某种机制,以便未完成的托管引用继续有效。在这些情况下,垃圾收集器是否真的确实移动了内存块,如果确实如此,它使用什么机制来保证托管引用的安全,我不知道。我不是垃圾收集器方面的专家。 (或者,正确地说,收集器——有很多实现。)

标签: c#


【解决方案1】:

Swap 函数仍然访问数组 3 或 4 次,与更简单的代码相比,Swap 函数没有任何性能优势。如果重复使用它可能会很有用。

static void Swap(ref int a, ref int b) 
{     
    int temp = a;  //<-- Here, a is in the array
    a=b;           //<-- a and b are in the array
    b=temp;        //<-- b is in the array
}

垃圾收集器不会释放您有引用的内存,就像您通过引用传递时那样。

【讨论】:

    【解决方案2】:

    堆栈可能如下所示:

    • qSort() 有对数组的引用
    • 交换()

    所以如果 GC.Collect() 在 swap 中执行,在 qSort() 中仍然有对数组的引用,这意味着它不会被收集。

    【讨论】:

      猜你喜欢
      • 2011-02-03
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 2016-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多