Excel VBA:销毁对象集合是否会破坏每个对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5690493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Excel VBA: Does destroying a collection of objects destroy every single object?
提问by Steve06
Say I have a collection MyCollection
of objects of MyClass
.
说我有一个收集MyCollection
的对象MyClass
。
Does Set MyCollection = Nothing
call each contained object's destructor or should I take care of setting each object = Nothing
individually?
是Set MyCollection = Nothing
调用每个包含对象的析构函数还是我应该= Nothing
单独设置每个对象?
I obviously care for reasons of memory leakage.
我显然关心内存泄漏的原因。
Dim MyCollection As Collection
Set MyCollection = New Collection
... 'add objects of type MyClass here
Set MyCollection = Nothing
Does destroying this class call every single object's destructor?
销毁此类会调用每个对象的析构函数吗?
回答by Dick Kusleika
All the MyClass objects will be destroyed when you destroy MyCollection, unless they are referenced somewhere else.
当您销毁 MyCollection 时,所有 MyClass 对象都将被销毁,除非它们在其他地方被引用。
VBA uses a reference counter on the class. It ticks up one every time there's a reference to the class and ticks down one every time a reference is destroyed. As long as MyCollection is something and is in scope, every MyClass reference counter contained therein will be at least one. If the reference counter is exactly one, destroying MyCollection will tick every element's reference counter down to zero and it will be garbage collected.
VBA 在类上使用引用计数器。每次有对类的引用时它都会增加一个,每次引用被销毁时它都会减少一个。只要 MyCollection 是某物并且在范围内,其中包含的每个 MyClass 引用计数器将至少是一个。如果引用计数器正好是 1,则销毁 MyCollection 会将每个元素的引用计数器标记为 0,并且它将被垃圾收集。
The last MyClass variable in the middle of your sub will reference one instance of MyClass unless you explicitly set it to Nothing. One class variable isn't likely going to cause a noticeable memory problem.
子中间的最后一个 MyClass 变量将引用 MyClass 的一个实例,除非您明确将其设置为 Nothing。一个类变量不太可能导致明显的内存问题。
Sub MakeClassColl()
Dim MyCollection As Collection
Dim i As Long
Dim clsMyClass As MyClass
Set MyCollection = New Collection
For i = 1 To 3
Set clsMyClass = New MyClass
MyCollection.Add clsMyClass
'Check1
Next i
Set MyCollection = Nothing
'Check2
End Sub
Check1:
检查1:
- i=1: MyClass1 (instance 1) has a reference counter of 2. One for the variable, one for the collection
- i=2: MyClass1 has an rc of 1 (lost clsMyClass, still has collection), MyClass2 has an rc of 2
- i=3: MyClass1 still 1, MyClass2 drops to 1, MyClass3 has an rc of 2
- i=1:MyClass1(实例1)的引用计数器为2。一个用于变量,一个用于集合
- i=2:MyClass1 的 rc 为 1(丢失 clsMyClass,仍然有集合),MyClass2 的 rc 为 2
- i=3:MyClass1 仍为 1,MyClass2 降为 1,MyClass3 的 rc 为 2
Check2:
检查2:
- Every MyClassi instance in the collection drops by one. MyClass1 and 2 go to zero. MyClass3 drops to 1 because clsMyClass still references it (I didn't destroy clsMyClass after adding it to the collection).
- 集合中的每个 MyClassi 实例减一。MyClass1 和 2 归零。MyClass3 下降到 1,因为 clsMyClass 仍然引用它(在将它添加到集合后我没有销毁 clsMyClass)。
回答by jtolle
The short answer is yes. In the below example, which is very similar to yours except that it shows one particular way you might have created your MyClass instances, all of the individual instances of MyClass will be destroyed right after the collection is destroyed:
简短的回答是肯定的。在下面的示例中,它与您的示例非常相似,只是它显示了您可能创建 MyClass 实例的一种特定方式,MyClass 的所有单个实例都将在集合被销毁后立即销毁:
Dim MyCollection As Collection
Set MyCollection = New Collection
Call MyCollection.Add(New MyClass)
Call MyCollection.Add(New MyClass)
Call MyCollection.Add(New MyClass)
Set MyCollection = Nothing
The longer answer is that it depends. The answer is "yes" if the only reference to the contained objects is the one held by the collection, which is the case in your simple example. VBA will know that all of your MyClass instances are no longer referenced anywhere and destroy them. (This will result in a call to each object instance's Class_Terminate
method.)
更长的答案是它取决于。如果对所包含对象的唯一引用是集合所持有的对象,则答案为“是”,在您的简单示例中就是这种情况。VBA 将知道您的所有 MyClass 实例不再在任何地方被引用并销毁它们。(这将导致调用每个对象实例的Class_Terminate
方法。)
But you have to be careful if you have made other references to those objects. There is nothing magic about the statement Set MyCollection = Nothing
. It's the fact that doing that causes VBA to destroy the collection, which in turn causes it to destroy the object within. (And of course, the collection is only destroyed by that line if MyCollection contaqins the only reference to it.)
但是,如果您对这些对象进行了其他引用,则必须小心。该语句没有什么神奇之处Set MyCollection = Nothing
。事实上,这样做会导致 VBA 销毁集合,从而导致它销毁其中的对象。(当然,只有当 MyCollection 包含对它的唯一引用时,该集合才会被该行销毁。)
A good source to learn more about how VBA object lifetimes is the old Visual Basic 6.0 Programmer's Guide, specifically the section on "Object References and Reference Counting":
旧的 Visual Basic 6.0 程序员指南,特别是“对象引用和引用计数”部分,是了解有关 VBA 对象生命周期的更多信息的一个很好的来源:
http://msdn.microsoft.com/en-us/library/aa263495(v=VS.60).aspx
http://msdn.microsoft.com/en-us/library/aa263495(v=VS.60).aspx