对 Visual Basic 中数组的浅拷贝的混淆
Confusion over shallow copies of arrays in 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
My understanding is that a shallow copy of an array copies the array variable, so that you have two pointers to the same memory location on the heap.
没有。它创建了一个 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
为了说明为什么这实际上是一个 'shallow' 副本,请检查它如何与引用类型一起使用。
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
相同。在这种情况下,程序的内存看起来有点像这样:
我的理解是,数组的浅拷贝会复制数组变量,因此您有两个指向堆上同一内存位置的指针。但是根据这个逻辑,下面的代码应该可以工作,但它没有:
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
My understanding is that a shallow copy of an array copies the array variable, so that you have two pointers to the same memory location on the heap.
没有。它创建了一个 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
为了说明为什么这实际上是一个 'shallow' 副本,请检查它如何与引用类型一起使用。
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
相同。在这种情况下,程序的内存看起来有点像这样: