References

reading

Cyganek section 3.11

References in C++ provide access to an object indirectly. It essentially becomes another name for the object and allows you to read and write to its memory directly.

We use the & operator to create a reference.

Here’s a simple example:

int x{10};
int &x_ref = x;

x_ref++;

Since x_ref is a reference for x, modifying its value directly modifies x ‘s value as well.

Note

You can define the reference as:

int& x;

or

int &x;

Important

A reference must be initialized when it is created. You cannot do:

double x{3.14};
double &x_ref;

x_ref = x;

We can create a const reference that provides only read access to an object:

int a = 1.0
const int& a_ref = a;

Now if we try to update a through a_ref, we’ll get an error.

const references will be very useful when we start writing functions and wish to pass objects in a read-only.

Note

You cannot make a reference to a reference.

A great use of references is to access and modify data in containers (like strings, vectors, and arrays) via a ranged-for loop.

Note

Recall in our array examples, we used references to loop over rows and columns and set the elements. Let’s look at that again.

Here’s an example showing different ways of accessing elements of a vector and whether we can modify them:

Listing 15 vector_modify.cpp
#include <iostream>
#include <vector>

int main() {

    std::vector<double> container(10, 0.0);

    // here "e" is just a double that is initialized via a copy to the
    // current element of container.  Since it is not a reference, it
    // is disconnected completely from container.

    for (auto e : container) {
        e = 1.0;
    }

    std::cout << "current vector: ";
    for (auto e : container) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    // now we create a reference (double&) to the current element in
    // the container.  This means that "e" is sharing the exact memory
    // in the vector as the current element, so if we modify it,
    // container is modified too.

    for (auto& e : container) {
        e = 2.0;
    }

    std::cout << "current vector: ";
    for (auto e : container) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    // this is access via iterators that we saw previously.  An
    // iterator can be thought of as a pointer to the element, and we
    // need to dereference it to access its value.

    for (auto it = container.begin(); it < container.end(); ++it) {
        *it = 3.0;
    }

    std::cout << "current vector: ";
    for (auto e : container) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

}

try it…

Let’s modify our example from last class with the Planet type to add the period as a member and fill the period automatically via Kepler’s law in a loop.

try it…

What do you think happens with this code?

int a{0}, b{1};
int& r = a, rr = b;