In C++, references (&) are a crucial concept that allows more efficient variable manipulation by avoiding unnecessary data copies. However, for beginners, the syntax and usage scenarios of references can be a bit abstract. Don’t worry! Today, we’ll clarify the basic usage of references from three aspects: “what it is,” “how to use it,” and “what to watch out for.”
1. What Exactly is a Reference?¶
Imagine you have a friend named “Xiaoming” who has an alias “Mingge.” Whether you call him “Xiaoming” or “Mingge,” you’re referring to the same person. In C++, a reference is like this “alias” — a reference is an “alias” for a variable, sharing the same memory space as the original variable. Modifying the reference’s value is equivalent to modifying the original variable’s value.
For example:
int a = 10; // Define variable a with value 10
int &b = a; // Define reference b, which is an alias for a
a = 20; // Modify the original variable a
cout << b; // Output b: 20 (since b is an alias for a, it has the same value as a)
Here, b is a reference to a, and b and a are essentially the same thing.
2. Basic Usage of References¶
1. Definition and Initialization¶
A reference must be bound to an existing variable at definition and cannot be “uninitialized” or “temporarily bound.” The syntax is: type &reference_name = original_variable;
Correct Example:
int x = 5;
int &y = x; // y is an alias for x, binding successfully
Incorrect Examples (Common Mistakes for Beginners):
int &z; // Error! Reference must be initialized and cannot be undefined
int &w = 10; // Error! A normal reference cannot bind to a temporary constant (10 is a temporary variable)
2. References as Function Parameters¶
When a function parameter is a reference, modifications to the reference inside the function directly affect the original variable (avoiding the copy overhead of “pass-by-value”).
Scenario: Swap the values of two variables
// Pass-by-value (copies x and y, modifying copies)
void swap_value(int a, int b) {
int temp = a;
a = b;
b = temp;
}
// Pass-by-reference (directly modifies original variables x and y)
void swap_ref(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 1, y = 2;
swap_value(x, y); // x and y remain unchanged (swap_value modifies copies)
cout << "x=" << x << ", y=" << y << endl; // Output: x=1, y=2
swap_ref(x, y); // x and y are swapped
cout << "x=" << x << ", y=" << y << endl; // Output: x=2, y=1
return 0;
}
Key Point: Passing by reference directly binds the function parameter to the actual argument, avoiding extra copies and improving efficiency.
3. References as Function Return Values¶
When a function returns a reference, it returns the reference to the original variable, not a copy. However, returning a reference to a local variable is prohibited (the local variable will be destroyed after the function ends, leading to undefined behavior).
Correct Example: Return a reference to a global/static variable
int global = 100; // Global variable
int &func() {
return global; // Return a reference to the global variable
}
int main() {
func() = 200; // Modify the reference returned, which changes the value of global
cout << global; // Output: 200
return 0;
}
Incorrect Example: Return a reference to a local variable
int &bad_func() {
int temp = 10; // Local variable, destroyed after the function ends
return temp; // Error! Returning a reference to a destroyed variable
}
int main() {
int &a = bad_func(); // This will get a garbage value (undefined behavior)
cout << a; // Output may be a random number
return 0;
}
4. const References (Constant References)¶
A reference modified by const is called a “constant reference,” with two key uses:
- Bind to temporary variables (not allowed for normal references);
- Prevent modification of the original variable through the reference (read-only access).
Example 1: Binding Temporary Variables
// Normal references cannot bind to temporary variables (int &c = 5; will error)
const int &c = 5; // Valid! Constant references can bind to temporary variables (temporaries are stored)
cout << c; // Output: 5
// Constant references can also bind to expression results
int x = 10, y = 20;
const int &d = x + y; // x+y is a temporary variable, d is its reference
cout << d; // Output: 30
Example 2: Prevent Modification of the Original Variable
void print(const int &a) { // Function parameter is a const reference, cannot modify a
// a = 30; // Error! const references cannot modify values
cout << a;
}
int main() {
int b = 20;
print(b); // Output: 20
return 0;
}
3. References vs. Pointers: Don’t Confuse Them!¶
Both references and pointers enable indirect access to variables, but they differ in syntax and use cases:
| Feature | Reference (&) | Pointer (*) |
|---|---|---|
| Definition | int &a = b; (must initialize) |
int *a = &b; (may or may not initialize) |
| Null Value | Cannot be null (must bind to a variable) | Can be null (int *a = nullptr;) |
| Target Change | Cannot change target after initialization | Can change target anytime (a = &c;) |
| Dereferencing | No need to dereference (use a directly) |
Need to dereference (*a) |
| Syntax Simplicity | More intuitive (a = 10;) |
Slightly more complex (*a = 10;) |
Summary: A reference is an “alias” for a variable, while a pointer is a “variable address.” References are safer and more concise, suitable for parameters/return values; pointers are more flexible, ideal for dynamic memory management (e.g., new/delete).
4. 3 Must-Know Notes for Beginners¶
- References Must Be Initialized:
int &a;will directly error; must writeint &a = b;. - Never Return a Reference to a Local Variable: Local variables are destroyed after the function ends, leading to “dangling references.”
- Special Use of const References: Must use
constwhen binding to temporary variables; otherwise, a compilation error occurs.
5. Summary¶
References are a powerful feature in C++ for efficient variable manipulation. Remember:
- A reference is an “alias” for a variable, sharing the same memory space.
- Passing by reference avoids copying, improving efficiency.
- Avoid returning references to local variables.
- const references can bind to temporary variables and prevent modification of the original variable.
It may seem a bit tricky at first, but with practice (e.g., swap functions, const reference binding), you’ll quickly master it. In the next article, we’ll explore advanced reference usage in classes and functions. Stay tuned!