首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ByVal是个谎言吗?

ByVal是个谎言吗?
EN

Stack Overflow用户
提问于 2018-04-15 18:28:24
回答 2查看 251关注 0票数 3

我想我最近(终于)开始了解ByValByRef在VBA中的工作方式。

观察

在我迄今所读过的所有教程和引用中,ByRef总是“传递对象”,ByVal是“传递对象的副本”。对我来说,后者意味着对象在内存中的位置被复制,指向新位置的指针被返回。现在我意识到,情况并不总是如此,事实上,据我所知,很少是这样的:相反,大多数对象和类实际上都是通过ByRef传递的,即使在例程的签名中指定了ByVal

System.Collections.ArrayList以静默方式传递ByRef,如以下代码所示:

代码语言:javascript
复制
Sub test()
    Dim list1 As Object, list2 As Object
    Set list1 = CreateObject("System.Collections.ArrayList")
    list1.Add "foo"
    Set list2 = RemoveItem(list1)
    Debug.Assert list2.Contains("foo") = False 'as expected
    Debug.Assert list1.Contains("foo") = True  'raises error, meaning list1 was passed byref not byval
End Sub

Function RemoveItem(ByVal list As Object) As Object 'ByVal
    list.Remove "foo" 'expect to remove from a copy and return that
    Set RemoveItem = list
End Function

考虑到我对ByVal的了解,这让我感到惊讶。进一步的深入研究表明,要想从ByVal中获得一个我想要的副本,我需要传递的对象有一个方法来实现这个功能。对于ArrayList.Clone方法创建一个浅拷贝。所以我的职能是:

代码语言:javascript
复制
Function RemoveItem(ByRef list As Object) As Object 'ByRef or ByVal, makes no difference
    Dim listCopy As Object
    Set listCopy = list.Clone 'make a shallow copy of the object
    listCopy.Remove "foo" 'actually remove from a copy and return that
    Set RemoveItem = listCopy
End Function

VB Array在传递ByVal时会引发编译器错误,这可能是对此的警告

问题

所有这些让我思考:

  1. 类/对象的ByValByRef有什么区别(如果有的话)?
  2. 将某些类型(BooleanLong)与不能传递ByVal的类和类型区分开来
  3. 在库引用方面--可能不是用VB6 编写的东西。
    • 是否可以创建一个具有默认ByVal响应的对象?
      • 在Python中,您可以指定类如何对不同的关键字作出反应。我怀疑您是否可以在VBA中进行本机操作,但是用一种更通用的语言编写的对象可以说,检测它是否正在传递ByVal,并返回其本身的.Clone
      • 换句话说,VBA的内置数据类型是如何传递给ByVal的,其他对象如何模仿这种行为(同样,在Python中,一切都是对象,所以所有的行为都可以被复制*)。还是我不用担心这种事的发生?

代码语言:javascript
复制
- Is it possible to mimic an `Array`'s behaviour and raise a compiler error when passed `ByVal` - as an array has no clone method and cannot be readily copied so is always `ByRef`

  1. 是否有一个子、函数或方法可以让我创建对象的深拷贝?也就是说,复制一个对象使用的内存和创建对象的第二个副本的一般方法。

*轶事,我对Python很陌生

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-15 19:04:53

在我迄今所读过的所有教程和引用中,ByRef总是“传递对象”,ByVal是“传递对象的副本”。

你有上面的例子的链接吗?

  1. 对于对象(由类创建),ByVal类似于*foo,而ByRef类似于**foo
  2. 布尔和长是原语,因为原语ByVal类似于bar,而ByRef类似于*bar
      • 对象无法判断是传递了ByRef还是ByVal
      • VBA‘内置’数据类型在C/C++中有类似的类型,因此Long是32位整数,实际上Boolean也是,但只能接受两个值中的一个(0=False、-1=True)。您不必担心,VBA以安全的名义设置限制。

代码语言:javascript
复制
- If you want to enforce passing `ByRef` for your objects then create a Type instead of a class.

  1. 对于类,您必须编写自己的副本构造函数,包括浅的和深的。但是,只需使用浅层和深层的=就可以复制类型。

数组和类型被传递给ByRef,因为它们是在堆栈上创建的。

票数 3
EN

Stack Overflow用户

发布于 2018-04-15 19:06:17

对于VBA中的对象和类,在传递byval或byref方面没有真正的区别。传递byref意味着指针被传递'byref',对象保持不变。

如果您想一想,它对于(Excel)对象来说是有意义的;无论您是通过Range("A1") byref还是byval,它仍然是我们正在寻址的相同的单元格。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49845406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档