我的理解是,数组的浅表副本会复制数组变量,以便您有两个指向堆上同一内存位置的指针。但是根据这种逻辑,下面的代码应该可以工作,但是不能:
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
答案 0 :(得分:5)
我的理解是,数组的浅表副本会复制数组变量,这样您就有两个指针指向堆上相同的内存位置。
不。它创建一个 new 容器,该容器包含所有相同的项目,否则与以前的容器相同,但是这些容器本身位于堆上的不同位置。它不创建重复的参考前面的容器。
您所描述的只是参考。考虑以下代码:
Dim row As Long() = {1, 2, 3, 4}
Dim otherRow as Long() = row
在程序的内存现在看起来像这样一点:
Clone
确实会创建一个浅表副本-也就是说,它将创建一个 new 数组,该数组包含与原始数组相同的所有值。然后,在该新数组的第一项上设置该值,但这不会影响原始数组,因为这些是完全不同的数组,彼此之间没有运行时引用。考虑以下代码:
Dim row As Long() = {1, 2, 3, 4}
Dim otherRow as Long() = row.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
即使row
和row.Clone
引用了不同的数组,但这些数组中的值(Ref
的实例)是相同的,因此修改array(0).Value
是相同的修改row(0).Value
。在这种情况下,程序的存储器看起来有点像这样: