Common Mistakes with References
#include <iostream>
using namespace std;
int main() {
int total = 0, num = 1;
// int &ref; // Error: Reference must be initialized
// int &ref = 10; // Error: Cannot bind to literal
// int &ref = total + num; // Error: Cannot bind to expression result
// &ref = num; // Error: Cannot rebind reference
int &ref = total; // Correct initialization
ref = num; // Assignment, not rebinding
return 0;
}
Key considerations:
- Operations on references direct affect the bound object
- References to references are invalid
References vs Pointers
Fundamental Differences
- Nature: References are aliases, not objects. Pointers are objects storing addresses.
int value = 10;
int& ref1 = value;
int& ref2 = ref1; // Valid: Additional alias for 'value'
- Type Matching: References and pointers must match their bound/referenced types (exceptions for const references).
double d = 3.14;
// int& r = d; // Invalid
// int* p = d; // Invalid
- Initialization: References must be initialized; pointers can be uninitialized (wild pointers). References offer safer usage:
void printRef(const int& r) {
cout << r << endl; // No null check needed
}
void printPtr(const int* p) {
if (p) cout << *p << endl; // Null check required
}
-
Rebinding: References cannot be rebound; pointers can be reassigned.
-
Addressability: Referenecs have no separate address; pointers do.
-
Size:
sizeof(pointer)is platform-dependent (typically 8 bytes on 64-bit systems);sizeof(reference)returns the size of the referenced object. -
Preference: Prefer references when possible for clarity and safety.
Reference to Pointer
References to pointers are valid, but pointers to references are invalid:
int i = 42;
int* ptr;
int*& refPtr = ptr; // Reference to pointer
refPtr = &i; // Makes ptr point to i
*refPtr = 0; // Modifies i through ptr
To parse declaration: Read right-to-left. The symbol closest to the identifier defines its core nature.
Const Qualifiers with Pointers
int a = 10;
// Pointer to const int
const int* ptrA = &a;
// Const pointer to int
int* const constPtrA = &a;
// Const pointer to const int
const int* const constPtrConst = &a;
Parameter Passing Semantics
- Pointer Parameters: Changes to pointer's address don't affect caller
void modifyPointer(int* p) {
int local = 1;
p = &local; // Local change only
}
int main() {
int* mainPtr = nullptr;
modifyPointer(mainPtr);
// mainPtr remains nullptr
}
- Reference Parameters: Modify the referenced object directly
void modifyReference(int& r) {
int local = 1;
r = local; // Modifies original variable
}
int main() {
int val = 10;
int& ref = val;
modifyReference(ref);
// val becomes 1
}