\section{References and Pointers\label{sec:references}}
Although used already, the references need a revisit. References can be understood as aliases to (existing) objects. Compared to classical
pointers, they do not represent the address of the referenced objects, but the data of the objects directly. They can be seen as dereferenced pointers.
A reference variable can be declared like a regular variable, using additionally the reference qualifier \texttt{\&}:
\begin{minted}{c++}
TYPE & var1 = aliased_object; // (1)
TYPE && var2 = aliased_object; // (2) ... since C++11
\end{minted}
Where (1) is called a lvalue-reference \index{Reference!lvalue reference} and (2) a rvalue-reference \index{Reference!rvalue reference}. A reference
must be initialized directly as it is not possible to change which object the reference refers to.
This is a major difference to pointers.
\begin{minted}{c++}
int i = 0;
int& r = i; // r references i
r = 1; // changes the value of i => i == 1
i = 2; // also r == 2
\end{minted}
References itself are not objects and do not need own memory. That is why there are no arrays of references and no references of references!
Referencing something in memory could be understood as just storing the address of that memory. An address is something like an integer indicating the position in memory. But, we need more than just the address, we need the type of the data that we are
referring to, so that we can give the memory a meaning. This is called a pointer:
%
\cppline{TYPE * pointer = &OBJECT;}
%
where \texttt{OBJECT} is any \underline{lvalue-reference} type.
We have used the \texttt{\&} symbol before, to qualify/indicate a reference. In the context of pointers, this symbol is an (unary) operator, the
address-of operator, returning a pointer to the object in memory. A pointer type is indicated by the \texttt{*} qualifier.
The \textit{dual} operator to the address-of operator is the de-reference operator, giving a reference to the object, a pointer points to:
%
\cppline{TYPE & reference = *POINTER;}
%
where \texttt{POINTER} must be any object of pointer type. So, the dereferenced pointer is again an lvalue.
Pointers can be combined with \cpp{const} qualifiers, to either indicate that the addressed data is immutable or that the address value is constant.
This behaviour is determined by the position of the \cpp{const} qualifier, \ie
We have seen that arrays can be implicitly converted to pointers and pointers can be used similar to arrays. Can we allocate an array directly as
a pointer? Is it possible to have an array of dynamic size? One needs to initialize a pointer with the address of a memory block large enough to hold
the wanted array. This is accomplished by \emph{dynamic memory management}: memory of arbitrary size can be allocated and deallocated at runtime!
In C++ this is done with the operator \cpp{new} and \cpp{new[]} to allocate memory and construct objects in the newly allocated memory, and \cpp{delete} and \cpp{delete[]} to destruct the objects and deallocate memory.
For a single element:
\begin{minted}{c++}
TYPE * p = new TYPE; // allocation of one element of type TYPE
delete p; // deallocation of one element of type TYPE
\end{minted}
and for more than one element:
\begin{minted}{c++}
TYPE * p = new TYPE[ SIZE ];
delete[] p;
\end{minted}
Note, the \texttt{SIZE} parameter to \cpp{new[]} does not need to be a constant expression!
Examples:
\begin{minted}{c++}
char* s = new char[100]; // dynamic array of 100 elements
int n = 1024;
double* v = new double[n]; // dynamic size
float* f = new float; // single element
for (int i = 0; i < n; ++i)
v[i] = i*i;
*f = 1.41421356237; // dereference the pointer to get a reference
delete[] v; // new[] => delete[]
delete[] s; // new[] => delete[]
delete f; // new => delete
\end{minted}
One problem with dynamic arrays is that there is no way to get the size of that array, and there is no way for the compiler
to perform a boundary check. Access of a memory location outside of the allocated array size may lead to a \emph{segmentation fault} or
may simply overwrite the data stored at the specific memory location $\rightarrow$ hard to find errors.
\begin{guideline}{Rule}
\cpp{delete} (or \cpp{delete[]}) can be applied to pointers created by the corresponding operator \cpp{new} (or \cpp{new[]}). On other pointers
it may lead to undefined behavior (and often produces a runtime-error of the form ``invalid pointer''). Only call \cpp{delete} once on a pointer!
\end{guideline}
Another problem with dynamic arrays is that you cannot even see whether it is an allocated array, or just an uninitialized pointer variable. So,
here again the general rule applies: initialize variables directly on declaration. If you do not yet have an address to initialize the pointer with,
set it to zero, \ie
%
\cppline{TYPE * pointer = nullptr;}
%
where \cpp{nullptr} is a special object just for this case of initialization of pointers. After \cpp{delete}, reset the pointer to \cpp{nullptr} again.
Example:
\begin{minted}{c++}
int* p = nullptr;
p = new int[1234];
// ...
delete[] p;
p = nullptr;
if (p) { // test for p != nullptr
/* work with p */
}
\end{minted}
Who owns the memory of a pointer, \ie who is responsible for deleting that pointer? It is the one that has created the array, so do not forget to delete!
Otherwise you have a \emph{memory leak}. The aftermath of a pointer related bug, \eg array boundary violation or accessing deleted memory, may show up \underline{much later} than the actual position of the error.
\begin{guideline}{Principle}
Pointers are \emph{dangerous} and require careful programming. So, prefer library types like \cpp{std::vector} or \cpp{std::array} instead of
(dynamic/static) arrays.
\end{guideline}
\subsubsection{Pointer arithmetics}
Pointers used as addresses of arrays, \ie the address to the first element of the array, have their one arithmetic. Since addresses are like integers,
they can be incremented and decremented, meaning a movement of the pointer in memory.
Pointers are associated to a specific element type (underlying type of the data). Incrementing and decrementing thus moves the address by multiples of
the size of the underlying data. This means that \cpp{pointer + 1} points to the next element in an array, where \texttt{pointer} points to.
Examples:
\begin{minted}{c++}
int* vec = new int[10]; // vec points to the first element of the array
vec = vec + 1; // vec now contains the address (vec + sizeof(int)), that is:
// vec points to the second element of the array
vec++; // vec points to the third element of the array...
delete[] vec; // ERROR: Address of vec not allocated by a direct call to new[]
\end{minted}
Pointers can be incremented (\texttt{+, ++}), or decremented (\texttt{-, --}), pointers can be compared, comparing the underlying address.
Pointers can be dereferenced, giving a reference to the data it points to. Additionally, pointers have the subscript-operator \cpp{[n]} that is
equivalent to \cpp{*(pointer + n)}.
Requirement for using pointer arithmetic is that the data has a defined size (complete types). The ``empty-set'' type \cpp{void} can be used as a pointer type,
meaning just the address without any reference to the data-type of the stored data. Since \cpp{void} does not have a size, pointers to \cpp{void} cannot
All objects in a program have one of the following storage durations:
\begin{itemize}
\item\textbf{automatic} storage duration. The storage for the object is allocated at the beginning of the enclosing code block and deallocated at the end. All local objects have this storage duration, except those declared \cpp{static}, \cpp{extern} or \cpp{thread_local}.
\item\textbf{dynamic} storage duration. The storage for the object is allocated and deallocated per request by using dynamic memory allocation functions (\cpp{new} and \cpp{delete}).
\item\textbf{static} storage duration. The storage for the object is allocated when the program begins and deallocated when the program ends. Only one instance of the object exists. All objects declared at namespace scope (including global namespace) have this storage duration, plus those declared with \cpp{static} or \cpp{extern}.
\item\textbf{thread} storage duration. The storage for the object is allocated when the thread begins and deallocated when the thread ends. Each thread has its own instance of the object. Only objects declared \cpp{thread_local} have this storage duration.
\end{itemize}
The memory for \emph{dynamic arrays} is allocated ``on the heap'', meaning dynamic arrays have \emph{dynamic storage duration}. Dynamic arrays are not destroyed at
the end of a function or block scope. They are destroyed only by a call to \cpp{delete} or \cpp{delete[]}.
We have (static) arrays and dynamic arrays. The difference is that static arrays have a constant size, but automatic storage duration, whereas dynamic arrays
have a dynamic size but also dynamic storage duration. Both can be represented by pointers. What if we want to have a dynamic size, but an automatic
storage duration?
This is possible using the special pointer type \cpp{std::unique_ptr} or \cpp{std::shared_ptr}, sometimes referred to as ``smart pointers''. Both are library
So, the definition and usage is very close to classical pointers. But you don't need to call \cpp{delete} to free the memory.
The difference between both types is the criterion when to deallocate the memory:
\begin{itemize}
\item\cpp{std::shared_ptr} is a smart pointer that retains shared ownership of an object through a pointer. Several \cpp{shared_ptr} objects may own the
same object. The object is destroyed and its memory deallocated when either of the following happens:
\begin{itemize}
\item the last remaining \cpp{shared_ptr} owning the object is destroyed;
\item the last remaining \cpp{shared_ptr} owning the object is assigned another pointer via \cpp{operator=} or \cpp{reset()}.
\end{itemize}
\item\cpp{std::unique_ptr} is a smart pointer that owns and manages another object through a pointer and disposes of that object when the
\cpp{unique_ptr} goes out of scope. The object is disposed of using the associated deleter when either of the following happens:
\begin{itemize}
\item the managing \cpp{unique_ptr} object is destroyed
\item the managing \cpp{unique_ptr} object is assigned another pointer via \cpp{operator=} or \cpp{reset()}.
\end{itemize}
\end{itemize}
You can have multiple pointers pointing to the same object, \ie to the same memory location. Since a pointer is a simple type, it can directly be copied
to create a new pointer with the same address:
%
\begin{minted}{c++}
int data = 7;
int* p = &data;
int* q = &data; // second pointer pointing to the same object
int* p2 = p; // copy of the first pointer creates a new pointer
// pointing to the same object
\end{minted}
%
The same can be done with \cpp{shared_ptr}. They share the same resource, \ie can point to the same object. Whenever you copy a \cpp{shared_ptr}, an internal
counter is increased that counts how many pointers are pointing to the same object. Only if this counter is zero, the \cpp{shared_ptr} is destroyed at the
end of a scope:
%
\begin{minted}{c++}
{
std::shared_ptr<int> p{ new int(7) };
std::shared_ptr<int> q{ new int(7) }; // independent new pointer to another memory location
{
std::shared_ptr<int> p2 = p; // copy of the first pointer creates a new pointer
// pointing to the same object, the internal counter
// is increased
} // at the end of scope, the second pointer is released -> decrease of the internal
// counter
std::shared_ptr<int> p3 = p; // another copy of the first pointer, increases the counter
} // at the end of scope, p and p3 are released, decreasing the counter by 2 -> 0. The
// memory is finally deallocated.
\end{minted}
\begin{guideline}{Guideline}
Don’t use explicit \cpp{new}, \cpp{delete}, and owning * pointers, except in rare cases encapsulated inside the implementation of a
Namespaces allow the programmer to resolve name conflicts. Defining the same name in the same scope results in an error. Namespaces define
named (or unnamed) global scopes.
%
\cppline{namespace NAME { ... }}
%
Symbols declared inside the \cpp{namespace} block are visible only in this block. The \texttt{NAME} of the namespace can be used to explicitly
qualify a function-, class, or variable name inside this namespace. A classical example, that we have seen before, is the standard namespace \cpp{std::}.
The symbol \texttt{::} thereby is the \emph{name-resolution operator} and may be chained to address multiple nested namespaces:
%
\begin{minted}{c++}
namespace Q {
namespace V { // original-namespace-definition for V
void f(); // declaration of Q::V::f
}
void V::f() {} // OK
void V::g() {} // Error: g() is not yet a member of V
namespace V { // extension-namespace-definition for V
void g(); // declaration of Q::V::g
}
}
namespace R { // not a enclosing namespace for Q
void Q::V::g() {} // Error: cannot define Q::V::g inside R
}
void Q::V::g() {} // OK: global namespace encloses Q
\end{minted}
%
One can separate declaration and definition of symbols, but only symbols from sub-namespaces can be defined within a namespace. Not just the definition,
but also the access is by the name-resolution operator \texttt{::}.
Namespaces can contain functions, classes, global variables. The outer most surrounding scope is called the \emph{global namespace} and is addressed with
an empty name before the name-resolution operator.
\subsection{\cpp{using} Directive and Declaration}
The statement \cpp{using} allows to import names from another namespace. So, those names can then be used without any namespace qualification, without the
name-resolution operator.
Either, you can import all names from a namespace, by the using-directive \cpp{using namespace NAMESPACE}:
%
\begin{minted}{c++}
namespace scprog {
void foo() { /*...*/ }
}
int main() {
using namespace scprog;
foo(); // Calls foo() from the namespace scprog without scprog::
}
\end{minted}
This is allowed in namespace scope and block scope only. Every name from the import namespace is visible as if it were declared in the nearest enclosing namespace.
This does not import the functions or classes into the current namespace, but just makes the names visible. This is important for name-resolution, \eg
in function calls.
Note the following:
\begin{itemize}
\item If there is already a local name in the scope declared, the name from the using namespace is hidden by the local name
\item A name from the imported namespace hides a same name in an enclosing namespace of the scope
\item Importing the same name from multiple namespaces into a scope results in a compiler error
\item Importing a name that is the same in the global namespace, results in a compiler error
\end{itemize}
\begin{minted}{c++}
#include <iostream>
int foo() { return 1; } // (1)
namespace scprog1 {
int foo() { return 2; } // (2)
}
namespace scprog2 {
int foo() { return 3; } // (3)
int bar() {
using namespace scprog1;
return foo(); // OK: calls (3)
}
}
int main() {
using namespace scprog2;
using namespace scprog1;
std::cout << bar();
std::cout << foo(); // error: call of overloaded 'foo()' is ambiguous,