Skip to content
Lesson 9 of 15

Step 1 of 5 · Reading · ~3 min

Learn

Functions and References

References vs Pointers

By the end of this lesson you can write a function that changes the caller's variables, using either a reference (int&) or a pointer (int*), and you can say which one fits a given job.

The problem: parameters are copies

Last lesson showed that void tryToDouble(int n) works on a private copy, so the caller's variable never changes. Sometimes changing the caller's variable is exactly the point. C++ gives you two tools for that.

References: a second name

A reference is another name for a variable that already exists. You declare it with & after the type, and it must be bound to a variable on the line where it is declared:

int score = 40;
int& alias = score;   // alias and score are the SAME int
alias += 5;
std::cout << score << "\n";   // 45

There is no copy. Writing to alias writes to score. A reference cannot be null and cannot be re-bound to a different variable later; it names that one variable for its whole life.

The useful form is a reference parameter. The function's parameter becomes a second name for the caller's argument:

void addTo(int& total, int amount) {
    total += amount;
}

int bank = 100;
addTo(bank, 25);    // no & at the call site
addTo(bank, 5);
std::cout << bank << "\n";   // 130

Trace: on the first call total is bank, so bank becomes 125; on the second it becomes 130. amount has no &, so it is an ordinary copy.

Pointers: an address you follow

A pointer holds the address of a variable. &x takes the address, *p follows it to the variable:

void addToPtr(int* total, int amount) {
    *total += amount;     // follow the address, then add
}

int bank = 100;
addToPtr(&bank, 25);      // pass the address explicitly
std::cout << bank << "\n";   // 125

Same effect, more punctuation: & at every call, * at every use. What a pointer can do that a reference cannot: hold nullptr (meaning "no variable at all"), and be pointed somewhere else later. Use a reference by default; use a pointer when "maybe nothing" or "may point elsewhere" is part of the meaning.

const references

void show(const std::string& s) shares the caller's string without copying it, and const makes the compiler reject any write to s. This is the normal way to pass a large read-only value, the same idea as const auto& in a range-for.

The trap: a reference is not a saved copy

Because a reference is the variable, it cannot remember an old value:

int level = 3;
int& before = level;   // WRONG if you meant "remember 3"
level = 8;
std::cout << before << "\n";   // 8, not 3

int kept = level;      // a plain int is a real copy
level = 1;
std::cout << kept << "\n";     // 8

If you need the old value after the variable changes, store it in a plain int.

Common mistakes

  • Dropping the & from the parameters. The function then swaps its own copies and the caller sees nothing: input 3 7 prints 3 7.
  • Two assignments with no temporary. The first assignment overwrites one value before anything has read it, so both variables end up equal: input 3 7 prints 7 7.
  • Making the temporary a reference. int& for the holding variable aliases one of the parameters, so it changes along with it and you get 7 7 again. The holder must be a plain int.

Your exercise

Fill in the body of swap(int& a, int& b) so the caller's two integers trade values. The starter already reads the numbers, calls swap, and prints them; you only write the body. The likely mistake is losing one value because nothing held it while the other moved.

Up nextstd::vectorSTL Collections

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…