Parameters & Pass by Value/Reference
How you pass arguments into a function has real consequences for performance and correctness in C++. Unlike some higher-level languages, C++ gives you explicit control over whether an argument is copied, referenced, or pointed to.
Pass by Value
#include <iostream>
using namespace std;
void increment(int x) {
x = x + 1; // only modifies the local copy
}
int main() {
int a = 5;
increment(a);
cout << a << endl; // Output: 5 - unchanged!
return 0;
}Pass by Reference (&)
& after the type to declare a reference parameter.#include <iostream>
using namespace std;
void increment(int& x) {
x = x + 1; // modifies the caller's actual variable
}
int main() {
int a = 5;
increment(a);
cout << a << endl; // Output: 6 - changed!
return 0;
}Pass by const Reference (const &)
#include <iostream>
#include <string>
using namespace std;
// No copy of the string is made, and it cannot be modified here.
void printLength(const string& s) {
cout << s << " has " << s.size() << " characters" << endl;
// s += "!"; // would not compile - s is const
}
int main() {
string message = "Hello, world!";
printLength(message);
return 0;
}Pass by Pointer
nullptr and must be explicitly dereferenced with * to access the value it points to.#include <iostream>
using namespace std;
void increment(int* x) {
if (x != nullptr) {
*x = *x + 1; // dereference to modify the caller's variable
}
}
int main() {
int a = 5;
increment(&a); // pass the address of a
cout << a << endl; // Output: 6
increment(nullptr); // safe - the function checks for null
return 0;
}Comparison
Passing method | Copy made? | Can modify caller? | Can be null? |
|---|---|---|---|
By value (T) | Yes | No | No |
By reference (T&) | No | Yes | No |
By const reference (const T&) | No | No | No |
By pointer (T*) | No | Yes | Yes |
Key Points
Pass by value copies the argument; changes inside the function do not affect the caller.
Pass by reference (T&) avoids the copy and lets the function modify the caller's variable.
Pass by const reference (const T&) avoids the copy without allowing modification - ideal for large read-only arguments.
Pass by pointer (T*) allows modification and can represent "no value" via nullptr, but requires dereferencing.
Prefer const reference over pass-by-value for anything larger than a small primitive type.