C++ Pass By Reference

By default, C++ passes arguments to functions by value, which means the function receives a copy. Changing the copy does not affect the original variable. Sometimes you want a function to modify the caller's variable directly, or you want to avoid copying large data. For that, C++ lets you pass by reference using the & symbol.

Pass by value: working on a copy

When you pass a variable normally, the function gets its own copy of the value. Anything the function does to that copy stays inside the function. Once the function ends, the original variable in main() is unchanged.

The original is not changed

#include <iostream>
using namespace std;

void tryToChange(int x) {
  x = 100; // Only changes the local copy
}

int main() {
  int num = 5;
  tryToChange(num);
  cout << num << "\n"; // Still 5
  return 0;
}

// Outputs: 5

Pass by reference: working on the original

Adding & to a parameter type makes it a reference. A reference is another name for the caller's variable, not a copy. So when the function changes the parameter, it is really changing the original variable back in main().

The original is changed

#include <iostream>
using namespace std;

void changeIt(int &x) {
  x = 100; // Changes the caller's variable
}

int main() {
  int num = 5;
  changeIt(num);
  cout << num << "\n"; // Now 100
  return 0;
}

// Outputs: 100
Note: A common use of references is a swap function that exchanges two values. Without references, a swap would only swap the copies and the original variables would keep their values.

Swapping two variables

#include <iostream>
using namespace std;

void swapValues(int &a, int &b) {
  int temp = a;
  a = b;
  b = temp;
}

int main() {
  int first = 10, second = 20;
  swapValues(first, second);
  cout << "first = " << first << ", second = " << second << "\n";
  return 0;
}

// Outputs: first = 20, second = 10

const references for efficiency

References are also useful for large objects, such as long strings or vectors, because passing a reference avoids making an expensive copy. If you only want to read the data and not change it, add const. This gives you the speed of a reference plus a guarantee that the function will not modify the original.

  • Pass by value: use for small types you don't need to change (int, double, bool).
  • Pass by reference (T&): use when the function must modify the caller's variable.
  • Pass by const reference (const T&): use for large data you only need to read.
StyleSyntaxCopies data?Can modify original?
By valuevoid f(int x)YesNo
By referencevoid f(int &x)NoYes
By const referencevoid f(const string &x)NoNo