首页 > 解决方案 > 在 Visual Basic 中对数组的浅拷贝感到困惑

问题描述

我的理解是数组的浅拷贝复制了数组变量,因此您有两个指向堆上相同内存位置的指针。但是根据这个逻辑,下面的代码应该可以工作,但它不能:

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

标签: arraysvb.netparametersparameter-passingshallow-copy

解决方案


我的理解是数组的浅拷贝复制了数组变量,因此您有两个指向堆上相同内存位置的指针。

不会。它会创建一个容器,其中包含所有相同的项目,并且在其他方​​面与前一个容器相同,但容器本身位于堆上的不同位置。它不会创建对前一个容器的重复引用。

你所描述的只是一个参考。考虑这段代码:

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

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

reference

Clone确实会创建一个浅拷贝——也就是说,它将创建一个数组,其中包含与原始数组相同的所有值。然后,您在该新数组的第一项设置值,但这不会影响原始数组,因为它们是完全不同的数组,彼此之间没有运行时引用。考虑这段代码:

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

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

clone

If you want to modify the original array within the ChangeRow subroutine, simply don't call clone.

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

To illustrate why this is actually a 'shallow' copy, examine how this works with reference types.

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

Even though row and row.Clone refer to different arrays, the values in those arrays (the instances of Ref) are the same, so modifying array(0).Value is the same as modifying row(0).Value. In this case, the program's memory looks a little like this:

shallow copy


推荐阅读