byVal和byRef

 Tiger_Zhao真是个水平又高又耐心的好筒子,又帮我弄清楚了byVal和byRef的区别,小结在这里。

 

(1)VB里函数参数缺省是byRef的。

(2)简单的说。byRef参数是传地址,当函数内部改这个参数的值的时候会反映到调用函数的外部变量;而byVal参数是传值,函数内部不管怎么变动参数的值都不会影响到传值过来的外部变量。

(3)但是上面这个说法只适用于参数类型为普通值类型的时候。这时,在ByVal的时候,函数内部会生成一个临时变量

sub f(byval a as long) a=a+1 'a 就是堆栈上的 long 变量,你可以看做有初始值的函数内部变量 end sub '调用 dim b as long call f(b) '将 b 的值复制到堆栈

sub f(byref a as long) a=a+1 'a 是堆栈上的 long* 指针,本语句实际对指针指向的 long (外部)变量进行了 Add 操作 end sub '调用1 dim b as long call f(b) '将 b 的指针放到堆栈,因此 f() 修改 b 的值 '调用2 Dim b As Long Call f(b + 0) '自动分配一个临时变量(实际没有名称、我们暂命名为 _t)' '赋值 _t = b+0 '将 _t 的指针放到堆栈' '因此 f() 修改 _t 的值,不影响 b,从而达到了 byval 的目的

(4)而当参数的类型是对象时。ByVal 是 Class1*  :指向对象的指针;ByRef 是 Class1** :指向对象指针的指针。这时无论是ByVal还是ByRef其实都是在传地址,区别只体现在对象的地址是否能被变化。在ByVal状态下,外部对象的属性仍然是可以被变化的。

'Class1 Option Explicit Public ID As Long 'Module1 Option Explicit Sub Main() Dim c As Class1 Set c = New Class1 c.ID = 99 Debug.Print c.ID Call f1(c) Debug.Print c.ID Call f2(c) Debug.Print c.ID End Sub Sub f1(ByVal c1 As Class1) Dim cx As Class1 Set cx = New Class1 cx.ID = 1 Set c1 = cx End Sub Sub f2(ByRef c2 As Class1) Dim cx As Class1 Set cx = New Class1 cx.ID = 2 Set c2 = cx End Sub

在上面这个示例中,可以在 Debug.Print 中加入 Hex(ObjPtr(c)) 来观察,外部变量 c 的对象实例是否可变更,结果显示在byval的时候是不可变更的。

另外,在上面的示例中,在f1里写c1.id=88,因为这时候c1是指向c的,这时虽然byval,但是也可改c的值。这说明byval其实也是传地址的。

另外,“指向对象的指针”和“指向对象指针的指针”都是“指针"——4字节。

 

总之,不要简单地被ByVal所迷惑,而要清醒地意识到函数内部得到的参数的引用方式是值、指针还是指针的指针。

你可能感兴趣的:(c,Module,Class,vb,hex)