Normally, when a parameter is passed from to a function, the value of that parameter is copied into a variable in the function's frame. For example, if successor is defined by
int successor(int n) { return n+1; }then statement
r = successor(5);is performed as follows.
A frame for successor is created in the run-time stack. Within that frame is a spot to store parameter n.
Parameter n in the new frame is set to hold 5.
The body of successor begins running. It computes n+1, or 6.
Successor returns 6. The result is copied into a place where the caller can get it. Then the frame for successor is destroyed, and the caller resumes.
The caller gets the result of successor and stores it into variable r.
C++ allows a function's body to change the value of a call-by-value parameter. It only changes the variable in the function's frame, and has no effect other than that. But keep in mind that the coding standards for this course require a function not to change the value of any call-by-value parameter.
If you write an & character after the type of a parameter in a function heading, the parameter is said to be a reference parameter, or to use call by reference.
When the function is called, the parameter passed to it must be a variable, and that variable's memory address is passed to the function. Any time the function's body uses the parameter, it uses the variable at the address that was passed. For example, suppose that inc is defined as follows.
void inc(int& n) { n = n + 1; }Then statements
int w = 1; inc(w);are performed as follows.
Variable w is created and initialized to 1.
A frame is created for inc. In that frame there is a spot for parameter n.
The memory address of the caller's variable w is stored in n in the new frame. Any reference to n will automatically use variable w.
The body of inc begins to run. It needs to get the value of n so that it can add 1 to it. But n holds a memory address. The value at that memory address (which is the value of the caller's variable w) is fetched.
Expression n+1 evaluates to 2. Now inc needs to store that into n. But since n is a reference parameter, it is a memory address. Value 2 is stored in the memory at that address (which is where w is stored). So w is set to hold 2.
inc returns to its caller and its stack frame is destroyed.
Since call by reference passes a memory address, it is actually passing a pointer. But the pointer is hidden from you; it is taken care of by the compiler.
You often prefer to use an explicit pointer, and to manage the pointer yourself. Here is a version of inc (renamed incp) that passes an explicit pointer.
void incp(int* n) { *n = *n + 1; }If you compare that to the version of inc that uses & instead of *, you will see that this version has a * on each occurrence of n. What call by reference does is insert those asterisks implicitly for you.
To use incp, you must pass an explicit pointer. For example,
int w = 1; incp(&w);does that by using the & operator to get the address of a variable. With call-by-reference, the & is added for you at each place where you call the function.
So call by pointer is similar in spirit to call by reference, the difference being that pointers are dealt with behind the scenes with call-by-reference, but explicitly with call by pointer.
Call by pointer is really a special case of call by value where the value is a pointer.
Call by reference is available in C++ but not in C. In C, you must pass an explicit pointer instead of an implicit one.
Call by value and call by reference are mechanisms for passing parameters. But you often prefer to think in terms of what the parameters are used for from a more conceptual viewpoint. There are three logical calling modes.
C++ provides two physical parameter passing modes: call-by-value and call-by-reference. A third mode, call-by-pointer, is a special case of call-by-value where the parameter is a pointer.
Logical parameter passing modes are: in-parameters (information passed from the caller to the callee), out-parameters (variables that are used to pass information from the callee to the caller) and in-out-parameters (used to pass information both directions. When you are thinking about parameter passing, identify the logical mode that you need. Then use a suitable physical mode.
Call-by-value can only be used for in-parameters, but it allows the actual argument to be any expression. Call-by-reference and call-by-pointer can be used for out-parameters and in-out-parameters, since the parameter must be a variable (or a pointer to a variable).
Can you use call-by-value for an out-parameter? Answer
Are all in-parameters passed using call by value? Answer
Where are a function's call-by-value parameters stored? Answer
What does jump( ) return, where jump is writtten below, using function jumpHelper?
void jumpHelper(int x) { x = x + 1; } void jump() { int z = 40; jumpHelper(z); return z; }Answer
What does hop( ) return, where hop is writtten below, using function hopHelper?
void hopHelper(int& x) { x = x + 1; } void hop() { int z = 40; hopHelper(z); return z; }Answer
What does romp( ) return, where romp is written below, using function rompHelper?
void rompHelper(int a, int& b) { b = a + 2; a = b + 1; } int romp() { int x = 4; int y = 25; rompHelper(x,y); return x + y; }Answer