What is actually passed in call by reference to a function?
void foo(int &a,int &b)
when I write
foo(p,q)
what is actually passed to the function. Is it the address of p and q?
What is actually passed in call by reference to a function?
void foo(int &a,int &b)
when I write
foo(p,q)
what is actually passed to the function. Is it the address of p and q?
It really gets passed a reference type - it's sort of like the address, but not quite. The actual address would be a pointer. References are less powerful than pointers, but are arguably safer. Wikipedia has a good description of the differences between pointers and references.
What's actually passed to the function is a reference. The named parameter b
becomes a synonym for the argument object q
.
How the compiler probably implements this that the caller places the address of q
on the stack or in a register before calling, and the callee uses that value to effect all accesses to b
. But it could be misleading to describe that as "actually passing" a pointer, because parameter passing is a concept at the level of the C++ language, and at that level it is not the same concept as passing a pointer. For instance, when you pass a pointer you can pass a null pointer, but when you pass a reference you cannot (validly). So it'd be wrong to say they're same thing.
That said, the person implementing the compiler might describe it as "actually passing a pointer", and you know what they mean. For comparison, if char
variables occupy 4-byte stack slots in the calling convention, they might say that the compiler is "actually passing an int". So it depends what "actually" is supposed to mean.
The way pass by reference works is defined by your compiler. In any event, they are passed as int&
which is an actual type in C++. Try this:
int x = 10;
int& y = x;
x = 100;
What do you think is the value of y? References are not quite pointers but aliases to a variable. The same mechanism that your compiler applies to int&
is used for pass by reference parameters.
Given the following program:
void byRef(int& x)
{
return;
}
void byVal(int x)
{
return;
}
void byPtr(int * x)
{
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
int x = 0;
byRef(x);
byVal(x);
byPtr(&x);
return 0;
}
The MSVC90 Assembly generated for the byRef
and for byPtr
calls are exactly the same which is:
lea eax, [x]
push eax
call byRef ;or byPtr
add esp, 4
You are passing a reference, which is not a pointer, and not an address -- but it is similar.
What "exactly" a reference is, isn't set in stone. The standard does not dictate the mechanisms for dealing with reference -- just the consequences of using them. Usually, they will be implemented as pointers.
Example:
int foo(int& a, int& b) { a = b; }
// Usage
int x, y;
foo(x, y);
This might generate the same machine code as:
int foo(int* a, int* b) { *a = *b; }
// Usage
int x, y;
foo(&x, &y);
But there's no guarantee of that, and the two are NOT equivalent (although they provide similar functionality).
When you take the address of a reference, you get the same address as the object that it is referring to. Example:
void foo(int& x) { std::cout << &x << std::endl; }
int y;
std::cout << &y << std::endl;
foo(); // This will print the same as above.
The other answers mention the semantic difference between a reference and a pointer.
In practice, every single compiler I've ever worked with implements them the same way -- passing a reference is really passing a pointer at the assembly level. This isn't specified in any standard, it's just the case in practice everywhere.
The question's come up on SO before: http://stackoverflow.com/questions/1640355/whats-the-low-level-difference-between-a-pointer-an-a-reference/1640362#1640362