VBA:我改变了arr(0),无法理解为什么arr(1)被改变了?

时间:2012-03-29 21:54:52

标签: excel-vba vba excel

我有这段代码:

Call MakeRoomForArrayItem(interAll, 0)

interAll(0).StartY = tempStartY
interAll(0).K = tempK

在第一行中,我成功地创建了一个新的细长interAll()。

然后我希望第二行和第三行仅影响interAll(0),但它们对interAll(1)执行相同的更改。为什么是这样?我没有为interAll(1)成功创建新对象吗?

Sub MakeRoomForArrayItem(ItemArray As Variant, ByVal ItemElement As Integer)
    Dim i As Integer
    ReDim Preserve ItemArray(LBound(ItemArray) To UBound(ItemArray) + 1)

    For i = UBound(ItemArray) - 1 To ItemElement Step -1
        Set ItemArray(i + 1) = ItemArray(i)
    Next
    'Erase values in object ItemArray(ItemElement) would be nice
End Sub

我在其他情况下成功使用了相同的功能。它可能与调用函数中缺少声明有关吗?

编辑:我通过添加

解决了问题
Set interval = New CInterval
Set interAll(0) = interval

你能告诉我这里到底发生了什么事,以便我不再犯同样的错误吗?

2 个答案:

答案 0 :(得分:1)

执行此操作时:

Set ItemArray(i + 1) = ItemArray(i)

您正在复制参考,而不是值。因此,在循环结束时,当i=0时,此行所说的是“将对ItemArray(0)中对象的引用复制到位置1”。因此ItemArray(0)ItemArray(1)都包含指向同一对象实例的引用。您应该能够使用调试器确认这一点。

答案 1 :(得分:1)

这取决于您传入MakeRoomForArrayItem的变量类型。如果您的数组持有值类型变量,例如Integer或Boolean,那么它将起作用,因为赋值语句

Set ItemArray(i + 1) = ItemArray(i)

正在复制一个值。但是,如果您使用的是通过引用传递的变量,那么您不会复制其值,而是复制对该变量的引用。在这种情况下,您似乎传递了一个类变量,该变量将通过引用传递。

编辑:当你调用New CInterval时,你实际上分配了一个新变量,而不是复制对前一个变量的引用。这就是你的修复工作的原因。如果没有你的修复,你只在内存中有一个“槽”来保存一个值,但你的数组多次引用该内存。修复之后,内存中的“插槽”与调用New CInterval的内容一样多,并且数组的每个元素都引用了新的内存位置。

以下代码可能会有所帮助:

Set interval1 = New CInterval   ' you have a single CInterval instance
Set interval2 = New CInterval   ' changes to interval1 or interval2 do not affect each other
Set interval3 = interval2       ' changes to interval3 also make changes to interval2,
                                ' because they are the same object.
Dim arr as CInterval(3)        
' Create a single array that has 3 elements, 
' which will hold 3 references to CInterval instances.  
' Those references may or may not be to the same actual CInterval instance.

Set arr(0) = interval1   ' the first element of the array references the first object instance
Set arr(1) = interval1   ' the second element of the array also references the first object instance
Set arr(2) = interval2   ' the third element of the array references the second object instance. 
                         ' Changes to this element will affect both interval2 and interval3, because they are references to the same object in memory.