C++: Function Parameter Passing
Last updated: 2026-08-26
In Lesson 10 we learned function basics and how functions can receive parameters.
But how exactly are parameters passed to functions? If a parameter is modified inside the function, does the outer variable change?
That's what this lesson covers — parameter passing methods.
1. Pass by Value
(1) 1.1 Basic Usage
Pass by value is C++'s default parameter passing method — the argument's value is copied to the parameter.
#include <iostream>
void modifyValue(int x) { // x is a parameter (copy)
x = 100; // Modifies the copy, doesn't affect the original variable
std::cout << "x in function = " << x << std::endl;
}
int main() {
int a = 5;
modifyValue(a); // Pass by value: a's value is copied to x
std::cout << "a in main = " << a << std::endl; // a is still 5
return 0;
}
💡 Key point: With pass by value, modifying the parameter inside the function does not affect the argument.
(2) 1.2 Pros and Cons of Pass by Value
| Pros | Cons |
|---|---|
| Safe (function can't modify the argument) | Large objects are expensive to copy (e.g., large arrays, large structs) |
| Clear logic | Can't make the function "return" multiple values |
2. Pass by Pointer
If you want a function to modify an external variable, you can pass its address (pointer).
(1) 2.1 Basic Usage
#include <iostream>
void modifyValue(int* x) { // x is a pointer
*x = 100; // Dereference: modify the value the pointer points to
std::cout << "*x in function = " << *x << std::endl;
}
int main() {
int a = 5;
modifyValue(&a); // Pass address: pass a's address to the function
std::cout << "a in main = " << a << std::endl; // a is now 100
return 0;
}
💡 Key point: With pass by pointer, the function can modify the argument's value through the pointer.
(2) 2.2 Why Can It Modify?
| Step | Explanation |
|---|---|
| 1 | int a = 5; — Allocate space in memory and store 5 |
| 2 | modifyValue(&a); — Pass a's address to the function |
| 3 | int* x receives the address, pointing to a's memory space |
| 4 | *x = 100; — Modify a's value through the pointer |
3. Pass by Reference
C++ introduced references — they are "aliases" for variables, safer and easier to use than pointers.
(1) 3.1 Basic Usage
#include <iostream>
void modifyValue(int& x) { // x is a reference (alias)
x = 100; // Modifying x modifies the original variable
std::cout << "x in function = " << x << std::endl;
}
int main() {
int a = 5;
modifyValue(a); // Pass by reference: no & needed, looks like pass by value
std::cout << "a in main = " << a << std::endl; // a is now 100
return 0;
}
💡 Key point: With pass by reference, the parameter is an alias of the argument — modifying the parameter modifies the argument.
(2) 3.2 Reference vs Pointer
| Comparison | Reference | Pointer |
|---|---|---|
| Syntax | int& x = a; |
int* x = &a; |
| Can be null | ❌ No (must be initialized) | ✅ Yes (can be nullptr) |
| Need to dereference | ❌ No (use directly) | ✅ Yes (use *x) |
| Can rebind | ❌ No (once bound, can't change) | ✅ Yes (can point to another variable) |
| Recommendation | ⭐⭐⭐⭐⭐ (prefer) | ⭐⭐⭐ (use when necessary) |
4. Comparison of Three Passing Methods
▶ Example 1: Swap Two Variables (Difficulty ⭐⭐)
Method 1: Pass by Value (Fails)
#include <iostream>
void swapFailed(int a, int b) { // ❌ Pass by value: modifies copies
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 3, y = 5;
swapFailed(x, y);
std::cout << "x = " << x << ", y = " << y << std::endl; // x=3, y=5 (not swapped)
return 0;
}
Output:
x = 5, y = 3
Method 2: Pass by Pointer (Works)
#include <iostream>
void swapPointer(int* a, int* b) { // ✅ Pass by pointer
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 3, y = 5;
swapPointer(&x, &y);
std::cout << "x = " << x << ", y = " << y << std::endl; // x=5, y=3 (swapped)
return 0;
}
Method 3: Pass by Reference (Works, Recommended)
#include <iostream>
void swapReference(int& a, int& b) { // ✅ Pass by reference (recommended)
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 3, y = 5;
swapReference(x, y); // Looks like pass by value, but is pass by reference
std::cout << "x = " << x << ", y = " << y << std::endl; // x=5, y=3 (swapped)
return 0;
}
5. When to Use Which Passing Method?
| Scenario | Recommended Method | Reason |
|---|---|---|
| Function doesn't need to modify the parameter | Pass by value or pass by const reference | Safe and clear |
| Function needs to modify the parameter | Pass by reference | Concise syntax, safe |
| Need to "return" multiple values | Pass by reference | Function can modify multiple reference parameters |
| Parameter is a large object (array, struct) | Pass by const reference | Avoid copy overhead |
| Need to represent "nothing" (e.g., lookup failure) | Pass by pointer | Pointer can be nullptr |
💡 Golden rule: Prefer pass by reference, use pass by pointer when necessary, and pass by value for small objects.
6. const Reference
If you don't want the function to modify the parameter but want to avoid copy overhead, use a const reference.
#include <iostream>
#include <string>
void printName(const std::string& name) { // const reference: can't modify name
std::cout << "Name: " << name << std::endl;
// name = "Alice"; // ❌ Error: can't modify a const reference
}
int main() {
std::string myName = "MOTO";
printName(myName); // No need to copy the entire string — efficient
return 0;
}
💡 Key point: const reference is one of the most commonly used parameter passing methods in C++, balancing safety and efficiency.
7. Arrays as Parameters
When an array is passed as a parameter, it decays into a pointer (covered in detail later).
#include <iostream>
// Array as parameter, need to pass the length
void printArray(int arr, int length) {
for (int i = 0; i < length; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
int main() {
int myArray[5] = {1, 2, 3, 4, 5};
printArray(myArray, 5); // Pass array name (which is the address of the first element)
return 0;
}
💡 Tip: When an array is passed as a parameter, the function doesn't know the array's length — you need to pass an additional length parameter.
8. Practice: Multiple Return Values
▶ Example 2: Calculate Quotient and Remainder (Difficulty ⭐⭐)
#include <iostream>
// Use reference parameters to "return" multiple values
void divide(int a, int b, int& quotient, int& remainder) {
quotient = a / b;
remainder = a % b;
}
int main() {
int a = 17, b = 5;
int q, r;
divide(a, b, q, r); // q and r will be modified
std::cout << a << " / " << b << " = " << q << " ... " << r << std::endl;
// Output: 17 / 5 = 3 ... 2
return 0;
}
Output:
17 / 5 = 3 ... 2
▶ Example 3: Default Parameters (Difficulty ⭐)
#include <iostream>
#include <string>
// Function with default parameters
void greet(const std::string& name, const std::string& greeting = "Hello") {
std::cout << greeting << "," << name << "!" << std::endl;
}
int main() {
greet("Zhang San"); // Use default parameter
greet("Li Si", "Good morning"); // Specify parameter
greet("Wang Wu", "Good evening"); // Specify parameter
return 0;
}
Output:
Hello,Zhang San!
Good morning,Li Si!
Good evening,Wang Wu!
Expected output:
Hello,Zhang San!
Good morning,Li Si!
Good evening,Wang Wu!
❓ FAQ
Q: What's the real difference between references and pointers? A: - A reference is an alias for a variable; a pointer is a variable that stores an address - A reference must be initialized; a pointer can be
nullptr- A reference can't be rebound; a pointer can - Prefer references unless you need to represent "nothing" (then use a pointer) Q: Why don't you need to specify the length when passing an array as a parameter? A: Because arrays decay into pointers.void foo(int arr)is equivalent tovoid foo(int* arr)— arr is actually a pointer, not an array. Q: Which is more efficient: pass by value, pass by reference, or pass by pointer? A: - Small objects (likeint): pass by value is most efficient (small copy overhead) - Large objects (like large arrays, large structs): pass by const reference is most efficient (avoids copying) - When you need to modify a parameter: pass by reference is best (concise syntax)
Q: What's most important about function parameters? A: Understand the core concepts first, then reinforce them through practice examples.
Q: How to efficiently practice function parameters? A: Start with simple examples, gradually increase difficulty, and always test your code.
📖 Summary
- Pass by value: Makes a copy; modifications inside the function don't affect the outside
- Pass by pointer: Passes an address; the function can modify the outside through the pointer
- Pass by reference: Passes an alias; modifications inside the function affect the outside (recommended)
- const reference: Can't modify, but avoids copy overhead (most commonly used)
- Arrays decay into pointers when passed as parameters; an additional length parameter is needed
📝 Exercises
-
Basic (Difficulty ⭐): Write a function
void addTen(int& x)that adds 10 to the passed variable. Test it inmain. -
Intermediate (Difficulty ⭐⭐): Write a function
void minMax(int arr, int length, int& min, int& max)that finds the minimum and maximum values in an array (using reference parameters to "return" them). -
Challenge (Difficulty ⭐⭐⭐): Write a program that implements "sort three numbers":
-
Write a function
void sortThree(int& a, int& b, int& c)that sorts three numbers from smallest to largest -
In
main, let the user enter three numbers, callsortThree, then output the sorted result
- Pass by value: copies the parameter; modifications inside the function don't affect the outside
- Pass by reference: shares memory; modifications inside the function affect the outside
- Default parameters go from right to left; can be omitted when calling
- Function overloading: same name with different parameters; determined at compile time
- const reference protects parameters from modification while avoiding copying
13. 🚀 Next Step
Now that you've learned parameter passing, next we'll learn recursion (Lesson 12) — the amazing technique of a function calling itself!