Lesson 5 | Call-by-reference |
Objective | Examine C++'s implementation of call-by-reference |
C++ Call by Reference
I am working as a C++ programmer using C++ 20.
How does C++ implement call-by-reference?
In C++20, as in previous versions of the language, call-by-reference is implemented by defining function parameters as references. A reference in C++ is essentially an alias for another variable. It allows a function to operate directly on the variables passed to it, rather than on copies of those variables. This means that any changes made to reference parameters within the function are reflected in the original arguments passed to it.
Two types of references can be used in C++:
1. **L-value References (`Type&`)**: These are the most commonly used references and allow a function to modify the actual argument passed to it.
2. **R-value References (`Type&&`)**: Introduced in C++11 and further utilized in C++20, R-value references are primarily used for implementing move semantics and perfect forwarding.
Here's an example demonstrating call-by-reference in C++:
#include
void increment(int& num) { // num is an l-value reference
num++; // Increment the value of the variable passed
}
void swap(int& a, int& b) { // a and b are l-value references
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 5;
int y = 10;
std::cout << "Before increment: x = " << x << std::endl;
increment(x); // Call by reference, x will be incremented
std::cout << "After increment: x = " << x << std::endl;
std::cout << "Before swap: x = " << x << ", y = " << y << std::endl;
swap(x, y); // Call by reference, x and y will be swapped
std::cout << "After swap: x = " << x << ", y = " << y << std::endl;
return 0;
}
In this example, the `increment` function takes an integer reference as an argument, allowing it to modify the original integer passed to it. Similarly, the `swap` function takes two integer references and swaps their values. This demonstrates the key advantage of call-by-reference: functions can modify the actual arguments, avoiding the need to return values to achieve the same effect.
Utilizing call-by-reference in C++ provides efficiency gains, especially when working with large data structures, as it avoids the overhead of copying data. Additionally, it allows for more expressive function interfaces in certain contexts, such as swapping, modifying, or efficiently passing large objects.
The chief use of reference declarations is in formal parameter lists. This allows C++ to have call-by-reference arguments directly, a feature not available in C.
Example
Let uslook at an example program that uses reference declarations and call-by-reference. The function
greater
exchanges two values if the first is greater than the second.
int greater(int& a, int& b){
if (a > b) { //exchange
int temp = a;
a = b;
b = temp;
return (1);
}
else
return (0);
}
If
i
and
j
are two
int
variables, then
greater(i, j)
uses the reference to i
and the reference to j
to exchange, if necessary, their two values. In traditional C, this operation must be accomplished using pointers and dereferencing.
Call-by-reference and const
When function arguments are to remain unmodified, it can be efficient and correct to pass them const
call-by-reference. This is the case for types that are structures.
struct large_size{
int mem[N];
//...other stuff
};
void print(const large_size& s){
//since s will not be modified
//avoid call-by-value copying
//...
}