在Visual Basic中对数组的浅表副本感到困惑

时间:2019-01-31 18:23:52

标签: arrays vb.net parameters parameter-passing shallow-copy

我的理解是,数组的浅表副本会复制数组变量,以便您有两个指向堆上同一内存位置的指针。但是根据这种逻辑,下面的代码应该可以工作,但是不能:

Sub Main()
    Dim row As Long() = {1, 2, 3, 4}
    ChangeRow(row.Clone)
    Console.WriteLine(row(0))
End Sub

Sub ChangeRow(ByVal array As Long())
    array(0) = 0
End Sub

Clone方法应该进行浅表复制。这意味着您将指向原始数组的指针作为参数传递。到目前为止,我在该主题上阅读的所有内容都表明这段代码有效,但事实并非如此。谁能解释?

有问题的方言是VB.Net

1 个答案:

答案 0 :(得分:5)

  

我的理解是,数组的浅表副本会复制数组变量,这样您就有两个指针指向堆上相同的内存位置。

不。它创建一个 new 容器,该容器包含所有相同的项目,否则与以前的容器相同,但是这些容器本身位于堆上的不同位置。它不创建重复的参考前面的容器。

您所描述的只是参考。考虑以下代码:

Dim row As Long() = {1, 2, 3, 4}
Dim otherRow as Long() = row

在程序的内存现在看起来像这样一点:

reference

Clone确实会创建一个浅表副本-也就是说,它将创建一个 new 数组,该数组包含与原始数组相同的所有值。然后,在该新数组的第一项上设置该值,但这不会影响原始数组,因为这些是完全不同的数组,彼此之间没有运行时引用。考虑以下代码:

Dim row As Long() = {1, 2, 3, 4}
Dim otherRow as Long() = row.Clone

在程序的内存现在看起来像这样一点:

clone

如果你想修改ChangeRow子程序中的原始阵列,根本不叫克隆。

Sub Main()
    Dim row As Long() = {1, 2, 3, 4}
    ChangeRow(row)
    Console.WriteLine(row(0)) ' outputs 0
End Sub

Sub ChangeRow(ByVal array As Long())
    array(0) = 0
End Sub

要说明为什么这实际上是“浅”副本,请检查它如何与引用类型一起工作。

Class Ref
    Public Value As Long 
    Public Sub New(ByVal value As Long)
        Value = value
    End Sub
End Class

Sub Main()
    Dim row As Ref() = {New Ref(1), New Ref(2), New Ref(3), New Ref(4)}
    ChangeRow(row.Clone)
    Console.WriteLine(row(0).Value) ' outputs 0
End Sub

Sub ChangeRow(ByVal array As Ref())
    array(0).Value = 0
End Sub

即使rowrow.Clone引用了不同的数组,但这些数组中的值(Ref的实例)是相同的,因此修改array(0).Value是相同的修改row(0).Value。在这种情况下,程序的存储器看起来有点像这样:

shallow copy