References
reading
Cyganek section 3.11
C++ references from Wikipedia
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:
#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;