VBA中ByVal的传参机制是否存在误导?
终于搞懂VBA里ByVal和ByRef的门道了!
最近我可算是把VBA里ByVal和ByRef的工作原理掰扯明白,之前被各种资料误导了好久,今天来分享下我的真实感悟。
我之前查过的所有教程和资料里,清一色把ByRef描述成「传递对象」,ByVal则是「传递对象的副本」。
我一开始信以为真,甚至脑补出了画面:ByVal就是把对象在内存里的位置整个复制一份,生成一块全新的内存区域,然后返回一个指向这个新地址的指针——结果现实给了我狠狠一巴掌,这种情况别说常见了,简直是极为少见!
实际情况完全不是这么回事:
- 对于大多数VBA对象和类来说,ByVal传递的其实是对象引用的副本,而不是对象本身的副本。也就是说,这个新的引用和原来的引用,指向的还是同一块内存里的同一个对象!
- 这就意味着,如果你通过ByVal传进来的引用修改对象的属性,原对象的属性会跟着变;只有当你把这个ByVal的引用重新指向一个全新的对象时,原对象才不会受到影响。
- 而ByRef就不一样了,它传递的是引用本身,如果你在子程序里修改这个引用指向的对象(包括直接替换成新对象),原对象的引用也会同步变化。
给大家看段测试代码更直观:
' 先自定义一个简单的类模块MyClass,添加一个属性MyProperty Sub TestByValByRef() Dim myObj As New MyClass myObj.MyProperty = "初始值" Debug.Print "调用ModifyByVal前:" & myObj.MyProperty Call ModifyByVal(myObj) Debug.Print "调用ModifyByVal后:" & myObj.MyProperty ' 输出"被ByVal修改后的属性" Debug.Print vbCrLf & "调用ModifyByRef前:" & myObj.MyProperty Call ModifyByRef(myObj) Debug.Print "调用ModifyByRef后:" & myObj.MyProperty ' 输出"全新对象的属性" End Sub Sub ModifyByVal(ByVal obj As MyClass) ' 修改属性,原对象会同步变化 obj.MyProperty = "被ByVal修改后的属性" ' 重新赋值引用,原对象不受影响 Set obj = New MyClass obj.MyProperty = "全新对象的属性" End Sub Sub ModifyByRef(ByRef obj As MyClass) ' 修改属性,原对象同步变化 obj.MyProperty = "被ByRef修改后的属性" ' 重新赋值引用,原对象的引用也被替换 Set obj = New MyClass obj.MyProperty = "全新对象的属性" End Sub
内容的提问来源于stack exchange,提问作者Greedo
相关产品推荐
相关产品推荐

