GSerg писал(а):Передача по значению сопровождается копированием объекта лишь в том случае, когда объект структурного типа. Когда объект ссылочного типа, передача по значению означает копирование не объекта, а ссылки на него.
alibek писал(а):Возможно, ByRef позволяет сбрасывать объект в Nothing в вызываемой процедуре (или присваивать ему другую ссылку).
GSerg писал(а):С точки зрения объекта - никакой; с точки зрения тебя - ты не сможешь установить в исходную переменную ссылку на другой объект (byval) или сможешь (byref); а с точки зрения эффективности - должно быть эффективнее byval, потому что дереференс 1 уровня, а не двух - но именно этот вопрос и был поставлен в топике.
alibek писал(а):В одном случае будет ссылка на объект, в другом случае ссылка на ссылку на объект. Во-втором случае, по идее, работать будет медленнее.
Option Explicit
Private Sub Form_Load()
Dim Reply As Long, lVarOne As Long, lVarTwo As Long
lVarOne = 128
lVarTwo = 512
Reply = TestFunction(lVarOne, lVarTwo)
'...
End Sub
Private Function TestFunction(ByVal lParamOne As Long, ByRef lParamTwo As Long) As Long
'...
End Function
Matt Curland в книге 'Advanced Visual Basic 6' писал(а):Parameters and IUnknown
Passing a variable or expression to a parameter is a lot like assigning the variable or expression to a variable of the same type as the parameter. Multiplying the two types of Set statement assignment (AddRef and QI) by the parameter modifiers (ByVal and ByRef) yields four permutations that VB must handle when passing to object parameters. We'll examine each of these permutations in terms of the IUnknown functions called in order to make it possible to pass the parameter.
ByVal, QI Required
Caller: QI the passed variable for the parameter's type and store the result in a temporary object variable. If the incoming variable is Nothing, initialize the temporary variable to Nothing. Pass the temporary variable.
Callee: AddRef the incoming ByVal parameter at the top of the function (VB-generated code does this, but COM object written in other languages might not).
Callee: Release the parameter when it leaves scope.
Caller: Release the temporary variable.
ByVal, No QI Required
Caller: AddRef the original variable and pass it.
Callee: AddRef when entering the function.
Callee: Release when exiting the function.
Caller: Release the original variable.
ByRef, QI Required
Caller: QI to get the correct type, and store the result in a temporary variable. Pass the address of the temporary variable.
Callee: Nothing to do.
Caller: If the temporary is not Nothing, QI the current reference in the temporary variable for the type of the passed parameter. Place the return reference in a second temporary variable.
Caller: Release the first temporary reference.
Caller: Release the reference in the original variable.
Caller: Move the value from the second temporary to the original variable.
ByRef, No QI Required
Caller: Pass the address of the variable (that's all).
Obviously, if you pass items of the same type, it makes the most sense to use ByRef passing, especially within your own project. Although IUnknown's overhead is not great, you need to be aware of the other implications of ByRef object parameters. If you pass ByRef to untrusted code, you give the callee the chance to invalidate your data. This isn't always a good idea. Also, if you pass an object to a method of an object in a different thread, don't use ByRef: this forces the marshaler to move your object in both directions. Of course, if you're retrieving an object instead of sending it, you need the ByRef parameter.
ByRef calls that involve mismatched types are clearly disastrous. I've rarely seen a case in which the developer really needs this capability. In most cases, the callee doesn't actually change the incoming reference, so you end up running a lot of unnecessary code, just in case. The QI that comes after the function call seems really bizarre because it happens after the function returns. If the extra QI isn't enough to scare you away from such calls, the amount of code generated in order to handle them should be. In the case of ByVal calls, the AddRef/Release call happens in the callee, so there is no extra IUnknown work to be done by the caller. However, in the case of ByRef calls, the entire IUnknown burden falls on the caller, so the code is generated everywhere the function is called with a mismatched type. The code required for a mismatched ByRef call is roughly twice the size of the code required for a mismatched ByVal. Avoid this construct unless you are truly using the parameter as a ByRef.
if you pass an object to a method of an object in a different thread, don't use ByRef: this forces the marshaler to move your object in both directions.
Ennor писал(а):if you pass an object to a method of an object in a different thread, don't use ByRef: this forces the marshaler to move your object in both directions.
Ты знал это с самого начала.
Сейчас этот форум просматривают: SemrushBot и гости: 1