C++ · Course navigation

C++ references, const, and auto

Pass large objects without copying, protect them with const, and let the compiler deduce types.

On this page
Before you start

C++ functions and vectors.

  • Pass large objects without copying, protect them with const, and let the compiler deduce types.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

A reference is another name for an existing object. A function that takes std::vector<int>& works on the caller's vector and can change it. A parameter of type const std::vector<int>& also avoids the copy but promises not to modify it, so the compiler rejects accidental changes. Passing big objects by const reference is the usual default.

auto lets the compiler deduce a variable's type from its initializer. Plain auto makes a copy, while auto& makes a reference to the original. A range-based for loop with int& changes the elements in place. Structured bindings, such as auto [low, high], unpack a pair or a tuple into named variables.

Code example

C++
#include <algorithm>
#include <iostream>
#include <vector>

void add_bonus(std::vector<int>& scores, int bonus) {
  for (int& s : scores) {
    s += bonus;
  }
}

int sum(const std::vector<int>& scores) {
  int total = 0;
  for (int s : scores) {
    total += s;
  }
  return total;
}

int main() {
  std::vector<int> scores = {82, 91, 76};
  add_bonus(scores, 5);
  std::cout << scores[0] << " " << scores[1] << " " << scores[2] << "\n";
  std::cout << sum(scores) << "\n";

  auto [low, high] = std::minmax_element(scores.begin(), scores.end());
  std::cout << *low << " " << *high << "\n";

  auto copy = scores;
  copy[0] = 0;
  std::cout << scores[0] << " " << copy[0] << "\n";

  auto& alias = scores;
  alias[0] = 100;
  std::cout << scores[0] << "\n";
}
Output
87 96 81
264
81 96
87 0
100

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1#include <algorithm>
2#include <iostream>
3#include <vector>
4
5void add_bonus(std::vector<int>& scores, int bonus) {
6 for (int& s : scores) {
7 s += bonus;
8 }
9}
10
11int sum(const std::vector<int>& scores) {
12 int total = 0;
13 for (int s : scores) {
14 total += s;
15 }
16 return total;
17}
18
19int main() {
20 std::vector<int> scores = {82, 91, 76};
21 add_bonus(scores, 5);
22 std::cout << scores[0] << " " << scores[1] << " " << scores[2] << "\n";
23 std::cout << sum(scores) << "\n";
24
25 auto [low, high] = std::minmax_element(scores.begin(), scores.end());
26 std::cout << *low << " " << *high << "\n";
27
28 auto copy = scores;
29 copy[0] = 0;
30 std::cout << scores[0] << " " << copy[0] << "\n";
31
32 auto& alias = scores;
33 alias[0] = 100;
34 std::cout << scores[0] << "\n";
35}

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
A non-const reference: the function changes the caller's vector.—
—
int& makes each s a reference to an element, so s += bonus changes the vector.—
—
A const reference avoids copying and forbids modification.—
—
Each score went up by 5.—
87 96 81
87 + 96 + 81.—
87 96 81
264
minmax_element returns two iterators, unpacked here by a structured binding.—
87 96 81
264
Dereference the iterators to read the smallest and largest values.—
87 96 81
264
81 96
Plain auto makes a copy, so changing it does not affect scores.—
87 96 81
264
81 96
The original keeps 87.—
87 96 81
264
81 96
87 0
auto& is a reference to the same vector, so the change shows in scores.—
87 96 81
264
81 96
87 0
scores[0] is now 100.—
87 96 81
264
81 96
87 0
100

Behind the scenes

How C++ processes this code

The C++ compiler produces a native executable. Execution enters main, where objects and function calls perform the work.

Cost and common mistakes

add_bonus and sum are O(n); minmax_element is O(n).

  • Forgetting & in a parameter or auto copies the whole object. Copying a big vector on every call is a common performance bug.
  • A reference must be bound when it is created and cannot be re-seated. Returning a reference to a local variable is undefined behaviour.
  • auto drops references and const unless you write auto& or const auto&.

Try it yourself

What happens if sum takes the vector by value instead?

Reveal answer and reasoning

It still works, but each call copies the whole vector first, which costs O(n) time and memory.

Further reading