Up to this point, we have seen how in C++, we can use pass-by-value, pass-by-reference and pass-by-constant-reference:
#include <iostream> int main(); void pass_by_value( int n ); void pass_by_reference( int &n ); void pass_by_constant_reference( int const &n ); int main() { int k = 42; std::cout << "k = " << k << std::endl << "Now passing by value..." << std::endl; pass_by_value( k ); std::cout << "k = " << k << std::endl << "Now passing by reference..." << std::endl; pass_by_reference( k ); std::cout << "k = " << k << std::endl << "Now passing by constant reference..." << std::endl; pass_by_constant_reference( k ); std::cout << "k = " << k << std::endl; return 0; } void pass_by_value( int n ) { n += 2; } void pass_by_reference( int &n ) { n += 3; } void pass_by_constant_reference( int const &n ) { // Not possible to modify the value of 'n' }
The C programming language, however, does not have pass-by-reference. We can, however, get around this by passing the address: if you want a function to change the value of an argument, you can pass the address of the argument and in the function, you change what is at that address. This is called pass-by-address or also pass-by-pointer:
#include <stdio.h> int main(); void pass_by_value( int n ); void pass_by_address( int *p_n ); void pass_by_constant_address( int const *p_n ); int main() { int k = 42; printf( "k = %d\nNow passing by value...\n", k ); pass_by_value( k ); printf( "k = %d\nNow passing by address...\n", k ); pass_by_address( &k ); printf( "k = %d\nNow passing by constant address...\n", k ); pass_by_constant_address( &k ); printf( "k = %d\n", k ); return 0; } void pass_by_value( int n ) { n += 2; } void pass_by_address( int *p_n ) { (*p_n) += 3; // Change what is at the address of 'p_n' } void pass_by_constant_address( int const *p_n ) { // Not possible to modify the value of '*p_n' }
In the two above functions, if we attempted to assign the value of the argument inside the pass-by-constant-reference and pass-by-constant-address; for example:
void pass_by_constant_reference( int const &n ) { // Not possible to modify the value of 'n' }
and
void pass_by_constant_address( int const *p_n ) { // Not possible to modify the value of '*p_n' }
respectively. If we try to compile each of these, we get the following compilation errors:
$ g++ sample.cpp sample.cpp: In function ‘void pass_by_constant_reference(const int&)’: sample.cpp:34:4: error: assignment of read-only reference ‘n’ n = 5; ^ $ gcc sample.c sample.c: In function ‘pass_by_constant_address’: sample.c:31:2: error: assignment of read-only location ‘*p_n’ *p_n = 5; ^
Critical warning:
In C++, you can also use pass-by-address, but pass-by-reference is the typical and expected mechanism for passing a parameter that is to have its value changed. If you are authoring C++ code, use the expected means of performing an operation, otherwise, you will likely to cause subsequent maintenance nightmares, especially if you mix both pass-by-reference and pass-by-address.