References
A reference is another name for a variable that already exists. Whatever you do through the reference happens to the original.
A second name
#include <iostream>
using namespace std;
int main() {
int score = 10;
int& ref = score; // ref is another name for score
ref = 25;
cout << score << endl;
score++;
cout << ref << endl;
cout << (&ref == &score) << endl; // the same address: one variable
return 0;
}25
26
1int& ref = score; doesn't copy anything. ref and score are the same variable, so changing either changes both. Two rules:
- A reference must be given its variable when it's created:
int& r;on its own doesn't compile. - It can't be moved to another variable later.
ref = other;copiesother's value intoscore.
Passing by reference
#include <iostream>
using namespace std;
void swapCopies(int a, int b) { int t = a; a = b; b = t; }
void swapRefs(int& a, int& b) { int t = a; a = b; b = t; }
int main() {
int x = 1, y = 2;
swapCopies(x, y);
cout << x << " " << y << endl;
swapRefs(x, y);
cout << x << " " << y << endl;
return 0;
}1 2
2 1An ordinary parameter is a copy, so swapCopies swaps its own copies and the caller's variables don't move. A reference parameter is the caller's variable itself. This is how C++ functions change their arguments without the pointers C needs.
Returning more than one value
#include <iostream>
using namespace std;
void minMax(const int values[], int n, int& lowest, int& highest) {
lowest = highest = values[0];
for (int i = 1; i < n; i++) {
if (values[i] < lowest) lowest = values[i];
if (values[i] > highest) highest = values[i];
}
}
int main() {
int temps[] = {21, 17, 25, 19, 30, 16};
int lo, hi;
minMax(temps, 6, lo, hi);
cout << "Lowest " << lo << ", highest " << hi << endl;
return 0;
}Lowest 16, highest 30A function returns one value, but it can fill in several reference parameters. These are called output parameters.
const references: no copy, no changes
#include <iostream>
#include <string>
using namespace std;
// const string&: the string isn't copied, and the function promises not to change it
int countVowels(const string& text) {
int n = 0;
for (char c : text)
if (string("aeiouAEIOU").find(c) != string::npos) n++;
return n;
}
int main() {
string line = "References avoid copying";
cout << countVowels(line) << endl;
cout << countVowels("works with temporaries too") << endl;
return 0;
}9
9Passing a string or vector by value copies every character or element. A const reference passes the original instead, and const lets the compiler stop the function from changing it. It also accepts temporary values, like the string literal on the last line.
The rule of thumb: pass small types (int, double, char) by value, big ones by const&, and use a plain & only when the function is meant to change the argument.
Changing elements in a loop
#include <iostream>
using namespace std;
int main() {
int prices[] = {100, 250, 80};
for (int p : prices) p *= 2; // p is a copy: the array doesn't change
for (int p : prices) cout << p << " ";
cout << endl;
for (int& p : prices) p *= 2; // p is each element itself
for (int p : prices) cout << p << " ";
cout << endl;
return 0;
}100 250 80
200 500 160 In a range-for loop, int p copies each element and int& p refers to it. GCC even warns about the first loop that p is set but never used: each copy is changed and thrown away. Use const auto& x to read big elements without copying them.
Never return a reference to a local
int& broken() {
int local = 5;
return local; // warning: reference to local variable 'local' returned
}local is destroyed when the function returns, so the reference would point at nothing. Returning a reference is fine for something that outlives the call, such as a member of an object or an element of a container that was passed in.
References and pointers
- A reference always refers to something; a pointer can be
nullptr. - A reference can't be re-pointed; a pointer can change what it points to.
- A reference uses the plain variable syntax; a pointer needs
*and&.
Reach for references by default, and pointers when "nothing" or "something else later" are real possibilities.