You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:00:11