There are two dichotomous issues here with similar vocabulary involved: value versus reference types, and passing variables by value versus by reference.
Value v. Reference Types
The first issue is value versus reference types. Value types are passed around through copying - usually. The value types are:
- Date
- Char
- U/Int(16/32/64)
- Decimal
- Single and Double
- Boolean
- Structs
- Enums
All but the above-listed types are reference types. When an object gets passed around, what is actually being passed is its memory address, which is often thought of as an int on 32 bit platforms and a long on 64 bit platforms.
Passing by Value v. By Reference
The second issue is passing a variable by value versus reference.
A variable is a slot at a certain position in memory that can hold stuff. For value types, it holds the actual value. For reference types, it holds the memory address of the object on the heap (or is Nothing).
By Value
When you pass a variable by value, whatever is at that variable's memory location is what gets copied. For value types, that means the value itself is copied. For reference types, what gets copied is the memory address of the object refered to by the variable.
By Reference
Remember that a variable is just a slot in memory for holding stuff. When you pass a variable by reference, you are passing the address of that slot (as opposed to the data in that slot).
If that variable is a value type, that slot holds the value itself, so the thing being passed is a pointer to the value.
If that variable is a reference type, the slot is holding a pointer to the object's location in memory, so the thing being passed is a pointer to your variable (just like with value types), which itself contains another pointer (not like value types) which leads to the memory location that holds the object referred to by the variable.
This allows a function to modify a variable in another function, like this:
Sub IPassByReference
Dim myVariable As Boolean = False
IReceiveByReference myVariable
Debug.Print(myVariable.ToString()) 'Always prints True
End Function
Sub IReceiveByReference(ByRef flag As Boolean)
flag = True 'the memory address of myVariable was passed.
End Function
Let's compare to the situation where you pass by value:
Sub IPassByValue
Dim myVariable As Boolean = False
IReceiveByValue myVariable
Debug.Print(myVariable.ToString()) 'Always prints False
End Function
Sub IReceiveByValue(ByVal flag As Boolean)
flag = True 'the value of myVariable was passed.
End Function
In the above example, Boolean is a value type. If it were an object, IReceiveByReference would have the power to point myVariable to an entirely new object, because it received the address of myVariable - not the address of the object to which myVariable points. By contrast, IReceiveByValue was only passed the contents of myVariable, so it cannot change myVariable to point to a new object. It could still change the object by setting its fields and properties and calling its methods, though.
Return By-Reference?
Although functions can pass variables by reference, they cannot return them that way. When a function returns, its local variables do not exist anymore (or are pending cleanup if they are heap-allocated). Functions therefore always return by value; because the local variables don't have valid memory addresses anymore, there aren't any variable references to return.
Putting it all together, when you return an object from a function, the only thing that is copied is the address of the object. When you return a value type from a function, the value itself is copied.
This means reference types are essentially value types, wherein the value is the memory address of an object on the heap, (or Nothing).
big_object
defined as a class or a structure? – Aleutian