A ParameterPassing mode where a reference (or if you want to be politically incorrect, a pointer) to the actual parameter is passed into the formal parameter; when the callee needs the formal parameter it dereferences the pointer to get it.
Consequences
- Introduces aliasing. In languages with LexicalScoping, can cause lots of surprising bugs as each FreeVariable is an implicit reference to the enclosing scope. What!? A parameter is, by definition, not a FreeVariable. [Sorry if not clear; what was meant was the following: It is an all-to-common source of bugs in PascalLanguage and others, where a variable is passed from an outer scope to an inner scope by a "var" parameter; and the inner scope also accesses the outer-scope's variable via LexicalScoping. That, of course, causes aliasing; the two variables refer to the same thing; and in arrangements where there are an intermediate series of calls between the two scopes, this is frequently not obvious--and a well-known source of bugs in block-structured languages like Pascal. You are correct in that parameters are not FreeVariables; implying that was not the intent.]
- Efficient for large data structures. Less efficient than CallByValue for things that can fit in a register. Most languages with CallByValue semantics optimize CallByValue by passing the address of the value to the called function when it is more efficient to do so compared to copying the entire value. [But they have to be careful to make sure that the callee doesn't modify the object (or the caller's object isn't being modified somehow by someone else), otherwise this optimization is no longer semantically correct]
- Allows the callee to modify the state of the caller.
- For immutable objects, semantically equivalent to CallByValue (main difference is performance).
- This is not true. You are confusing pointers (a.k.a. references in Java and many OO languages) and CallByReference. CallByReference passes an alias to a variable in the callers scope to the called function. The caller can change the contents of that variable. This is completely unrelated to whether the variable itself contains a reference to an immutable object.
- [Perhaps it's C/C++ background sneaking through... in a language with value semantics such as C/C++, pointers are how you do CallByReference. In languages with reference semantics (most OO languages, Java for objects but not for intrinsics), one could argue that the "handle" to the object is the value (and passing the handle is CallByValue); performing a second indirection and passing a reference to the handle (in C/C++ terminology, a Foo **) is how you do CallByReference. In which case, many OO languages do not allow CallByReference; using this definition (in Java) all calls are by value.]
- C++ has CallByConstReference?; where an argument is passed by reference but the callee is not allowed to modify it.
- This is semantically equivalent to CallByValue. Most languages perform this optimization without the programmer having to worry about it. See above.
- Found in many OO languages; optionally available in PascalLanguage (var parameters) and CeePlusPlus (reference parameters). Can be simulated in CeeLanguage with explicit pointer passing.
- Most OO languages do NOT pass by reference. They pass pointers to objects (which they call object references) by value. This is NOT the same as CallByReference.
It seems there is an alternate definition for Call By Reference being proposed. Would the proposer care to expand upon it?
My understanding is that there are only two ways to share values in computer memory, either one copies the value to a new memory location or one one shares the memory location of the value (assembly allows a third option, the sharing of values via registers).
The difficulty associated with making copies of objects is not due to memory use; most objects usually contain few bytes of data. Even strings rarely exceed 100 characters, i.e., are less than one screen line. Very few objects ever exceed 100 bytes in size and many are much smaller. Memory space is typically not a constraint in copying objects; the constraint is the copy algorithm. Copy algorithms are made complex by two issues: embedded objects and derived classes. When creating a copy of an object containing references to other objects, one needs to copy the referenced objects as well, not just copy the reference to the object (the former is known as "deep copying" while the latter is "shallow copying"). Class inheritance poses a greater challenge because when copying a reference to a base class, one needs to know to copy the entire child class. The program does not know the amount of memory space to allocate at compile time, making it extremely difficult to copy the value onto the stack because references to other values on the stack will be affected by the size of the copied object.
If there is an additional method for sharing values besides copying the value and sharing the memory location of the value, I would be interested in hearing it. If not, I think we will have to accept the original definition on this page of Call By Reference being pointer passing with some level of syntax covering it.
Well, there's CallByThunk. And CallByValueResult. CallByThunk is independent of CallByReference or CallByValue, either of those call types can be "thunked." CallByValueResult just appears to by a double copy, it is CallByValue with the return overwriting the original value. The two basic ways of sharing a value between a caller and a called method are still used.
The reason that this page is so confused is that it doesn't distinguish between lvalues and rvalues (LeftValues and RightValues in wiki syntax).
(text moved from PassByReference:)
There are two basic choices when passing parameters to a function / method:
- Pass by value [CallByValue]: you get a copy of the data or object
- Pass by reference: you get an alias of the data or object
If you have a parameter passed by reference, changes to it are reflected in the caller's value. Therefore your function can return values through its parameters.
CeePlusPlus example:
void f( int x )
{
x = x * 2;
}
Calling function f on an integer variable will leave the value unchanged. It is essentially redundant. However,
void g( int& x )
{
x = x * 2;
}
calling function g on an integer variable will double the value. CeeLanguage can approximate this behaviour through the use of pointers:
void h( int* x )
{
(*x) = (*x) * 2;
}
calling function h on a pointer to an integer variable will double the value.
"ByRef" in VisualBasic.
"ref Blah b" in C#.
See
ParameterPassing,
CallByValue,
ReturnByReference
CategoryCpp CategoryLanguageFeature