Commit 475ae43c authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Lecture notes updated

parent f3fb9168
\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!
\begin{minted}{c++}
int& a[3]; // error
int& &r; // error
\end{minted}
% -------------------------------------------------------------------------------------------------
\subsection{lvalues and rvalues / value categories}
See \url{https://en.cppreference.com/w/cpp/language/value_category}:
Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties:
a \emph{type} and a \emph{value category}. Each expression has some non-reference type, and each expression belongs to exactly one of the three
primary value categories: \emph{prvalue}, \emph{xvalue}, and \emph{lvalue}.
\begin{itemize}
\item a \emph{glvalue} (``generalized'' lvalue) is an expression whose evaluation determines the identity of an object, bit-field, or function;
\item a \emph{prvalue} (``pure'' rvalue) is an expression whose evaluation either \begin{itemize}
\item computes the value of the operand of an operator (such prvalue has no result object), or
\item initializes an object or a bit-field (such prvalue is said to have a result object). All class and array prvalues have a result object
even if it is discarded. In certain contexts, temporary materialization occurs to create a temporary as the result object;
\end{itemize}
\item an \emph{xvalue} (an ``eXpiring'' value) is a \emph{glvalue} that denotes an object or bit-field whose resources can be reused;
\item an \emph{lvalue} (so-called, historically, because lvalues could appear on the left-hand side of an assignment expression) is a
\emph{glvalue} that is not an \emph{xvalue};
\item an \emph{rvalue} (so-called, historically, because rvalues could appear on the right-hand side of an assignment expression) is a
\emph{prvalue} or an \emph{xvalue}.
\end{itemize}
\begin{figure}[ht]
\begin{center}
\includegraphics[width=.5\textwidth]{images/value_categories}
\caption{Diagram of value categories.\label{fig:value-categories}}
\end{center}
\end{figure}
This categorization results from the idea that every expression can be characterized by two orthogonal properties:
\begin{enumerate}
\item[i] \textbf{has identity}: Object that has an address, a pointer, the user can determine whether 2 copies are identical
\item[m] \textbf{can be moved from}: We are allowed to leave the source of a ``copy'' in some indetermined, but valid, state.
\item[$\sim$] has not the property.
\end{enumerate}
The combination \texttt{($\sim$i)($\sim$m)} does not really exists and thus, we have three leaf categories, see Figure \ref{fig:value-categories}.
Examples for lvalues, rvalues, and prvalues:
\begin{minted}{c++}
int i = 3;
int j = 4;
i; // the name of a variable is an lvalue
123; bool; 'c'; // literals (except for string literals) are prvalues
// a + b, a % b, a & b, a << b, and all other built-in arithmetic expressions are prvalues
int c = i * j; // OK, (p)rvalue on the right-hand side of an assignment
i * j = 42; // ERROR, rvalue not allowed on the left-hand side of an assignment
// more on lvalues:
i = 43; // OK, i is an lvalue
int* p = &i; // OK, i is an lvalue
int& foo(); // a function call, whose return type is lvalue reference is an lvalue
foo() = 42; // OK, foo() is an lvalue
int* p1 = &foo(); // OK, foo() is an lvalue
// more on rvalues:
int foobar(); // a function call, whose return type is non-reference is an prvalue
int j = 0;
j = foobar(); // OK, foobar() is an rvalue
int* p2 = &foobar(); // ERROR, cannot take the address of an rvalue
j = 42; // OK, 42 is an rvalue
\end{minted}
% -------------------------------------------------------------------------------------------------
\subsection{lvalue- and rvalue references}
We distinguish references to lvalues and rvalues as lvalue-references and rvalue-references, denoted by one or two \texttt{\&}, respectively. So,
lvalue-references refer to existing objects with an identity, \ie lvalues, whereas rvalues typically refer to something that goes out of scope, whose
lifetime ends. Rvalue references can be used to extend the lifetimes of temporary objects:
\begin{tabular}{p{0.35\textwidth}|p{0.65\textwidth}}
\begin{minted}{c++}
int f() { return 42; }
int& g(int& a) { return a; }
// f() is prvalue expr.
int i = f(); // OK
f() = 7; // ERROR
// g() is lvalue expr.
int j = g(i); // OK
g(i) = 3; // OK => i == 3
\end{minted}
&
\begin{minted}{c++}
int& k1 = f(); // ERROR
int&& k2 = f(); // OK
k2 += 1; // OK, rvalue-Reference extends lifetime
int& l1 = g(i); // OK
int&& l2 = g(i); // ERROR, cannot bind lvalue to
// rvalue-References.
// const-References
int const& k3 = f(); // OK
k3 += 1; // ERROR, const-ref. is non-mutable
int const& l3 = g(i); // OK
\end{minted}
\end{tabular}
In the example, the function \cpp{f()} only returns a temporary object (a number), that is not yet assigned to a variable. Rvalue-references can now
be used to refer to this value with a variable before it is finally destroyed.
\begin{example}
Example from \href{https://stackoverflow.com/questions/3716277/do-rvalue-references-allow-dangling-references}{Stackoverflow}:
\begin{minted}{c++}
T& lvalue();
T prvalue();
T&& xvalue();
T&& does_not_compile = lvalue();
T&& well_behaved = prvalue();
T&& problematic = xvalue();
\end{minted}
\end{example}
\begin{rem}
The ultimate usage of rvalue-references is, that you know that the object refereed to is going out of scope or is deleted afterwards, or is a
temporary at all, thus one can directly take the ownership of that object, without copying its content. This is called a move operation.
\end{rem}
% -------------------------------------------------------------------------------------------------
\subsection{Pointers}
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
%
\begin{minted}{c++}
int data = 42, data2 = 1234;
int const* i1 = &data;
*i1 = 7; // ERROR: cannot modify constant data
i1 = &data2; // OK: i1 now points to data2
int* const i2 = &data;
*i2 = 7; // OK: data is not const
i2 = &data2; // ERROR: cannot change address of const pointer
int const* const i3 = &data; // completely imutable
\end{minted}
Since references are not objects, one cannot declare a pointer to a reference (something like \cpp{int&*}), but a
pointer is a regular type representing an address, it can be referenced, \ie
%
\begin{minted}{c++}
int data = 42, data2 = 1234;
int* p = &data;
int*& r = p; // reference to pointer p
*r = 7; // changes value of data;
r = &data2; // changes stored address of p
\end{minted}
\begin{guideline}{Guideline}
Don't use pointers to pass data to functions, only if you have a strong reason to do so. Some style-guides use pointers as output arguments
in functions to not mix it up with input arguments. This is because you have to explicitly dereference the pointer in order to use it.
\end{guideline}
\section{Arrays and Dynamic Memory}
\subsection{Static Arrays}
So far, we had only data-types with 1 entry per variable (except for the library types \texttt{vector}, \texttt{pair} and \texttt{tuple}).
Arrays are compound data-types with a \underline{fixed} number of entries of the same type:
%
\cppline{TYPE variable[ SIZE ];}
%
where \texttt{SIZE} is an \emph{integral constant expression}.
Examples:
\begin{minted}{c++}
int n[5];
double f[ 10 ];
constexpr int len = 32;
char str[len];
\end{minted}
%
Those arrays can then be accessed by square-brackets, similar to \cpp{std::vector}, \eg
%
\cppline{n[2] = 7;}
%
Arrays can be pre-initialized. In that case, the array size can be omitted, \ie is detected
automatically by the compiler:
\begin{minted}{c++}
int n1[5] = {1, 2, 3, 4, 5};
int n2[] = {10, 9, 8}; // automatically size 3
\end{minted}
Multi-dimensional arrays are written with multiple square brackets:
%
\begin{minted}{c++}
int A[2][3]; // a 2 × 3 matrix
double B[5][4][3]; // an 5 × 4 × 3 tensor
\end{minted}
%
and can be understood as arrays of arrays (a matrix is and arrays of rows).
The initialization of multi-dimensional arrays is by lists of initializer-lists, \eg
%
\begin{minted}{c++}
double A[2][3] =
{
{1.0, 2.0, 3.0},
{4.0, 5.0, 6.0}
};
\end{minted}
\begin{rem}
An array can be pre-initialized with less elements than the given size. In that case the remaining entries are default-initialized, \ie
number types are initialized to zero and class-types using the default-constructor.
Example:
\cppline{int foo[5] {1,2,3}; // [1,2,3,0,0]}
(The assignment operator ``\cpp{=}'' is here replaced by \textit{Universal Initialization}.)
\end{rem}
A multi-dimensional array can be written with a one-dimensional initializer-list. In that case, the initialization happens arrays-wise.
%
\cppline{int foo[][2] {1,2,3,4}; // [1,2; 3,4]}
%
For multi-dimensional arrays only one size entry can be omitted. The shape must be deducible by the number of entries.
\subsubsection{Size of an array}
While the syntax for arrays is simple and clean, it lacks the direct possibility to get the size after the declaration. In C, you typically
use macros to deduce the size from the byte-size of the array, \ie
%
\cppline{#define SIZE(a) (sizeof(a) / sizeof((a)[0])) }
%
Note the usage of additional brackets, here.
Example:
\begin{minted}{c++}
int vec[5] {1,2,3};
static_assert(SIZE(vec) == 5);
int mat[][2] {1,2,3,4};
static_assert(SIZE(mat) == 4);
\end{minted}
\subsubsection{Arrays as function arguments}
Arrays can be (implicitly) converted to a pointer, \ie to a pointer to the first element of the array:
%
\begin{minted}{c++}
int a[3] = {1, 2, 3};
int* p = a; // pointer to the first element of the array
\end{minted}
%
This allows to pass arrays to functions, accepting pointers as arguments, \ie
%
\begin{minted}{c++}
void f1(int* p) { /* sizeof(p) != sizeof(a) */ }
void f2(int p[]) { /* sizeof(p) != sizeof(a) */ }
int a[3] = {1, 2, 3};
f1(a); // OK: a is converted to a pointer
f2(a); // OK: equivalent to f1
\end{minted}
%
But, then we loose any information about the array. It is just a pointer to the first element of that array.
Nevertheless, pointers to array data allow direct element access, like for the regular arrays:
%
\cppline{int a1 = p[1];}
The second form of passing arrays to functions is by array reference
%
\cppline{TYPE (&reference)[SIZE] = ARRAY;}
%
Example:
\begin{minted}{c++}
void g(int (&b)[3]) { /* sizeof(b) == sizeof(a) */ }
int a[3] = {1, 2, 3};
g(a);
\end{minted}
The problem here, we have to give the size in the function argument declaration, since the size of the arguments must be known
at compile-time and are fixed to exactly one size. It is not allowed to pass arrays of different size to that function.
\begin{rem}
\underline{Outlook:} Using \emph{templates}, we can write functions of arbitrary array size and can deduce that size automatically, \ie
\begin{minted}{c++}
template <class T, int N>
int array_size(T (&)[N]) { return N; }
template <class T, int N1, int N2>
std::pair<int,int> mult_array_size(T (&)[N1][N2]) { return {N1, N2}; }
\end{minted}
\end{rem}
% -------------------------------------------------------------------------------------------------
\subsection{Standard Arrays}
The problem with the size of the arrays, the argument passing to functions (and some more restriction) motivates to introduce a library type
that overcomes those problems. With \cxx{11}\marginpar{[\cxx{11}]} the type \cpp{std::array<T, Size>}\index{Array} was added to the standard
library:
\begin{minted}{c++}
#include <array>
// ...
std::array<int, 3> vec1 = { 1.0, 2.0, 3.0 };
std::array vec2 = {1, 2, 3}; // with C++17
std::cout << vec1[1];
\end{minted}
The difference to the other library type \cpp{std::vector} is, that an array must have a fixed size, and the data is allocated to the ``stack''
and not dynamic memory allocated on the ``heap'' as in the vector implementation (see below).
\begin{guideline}{Principle}
Prefer the library type \cpp{std::array} over classical arrays.
\end{guideline}
% -------------------------------------------------------------------------------------------------
\subsection{Dynamic memory allocation}
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
be used in pointer arithmetics.
% -------------------------------------------------------------------------------------------------
\subsection{Storage duration}
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[]}.
% -------------------------------------------------------------------------------------------------
\subsection{Smart pointers}
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
types defined in the header \cpp{<memory>}.
Example:
\begin{minted}{c++}
#include <memory>
//...
std::shared_ptr<int> ip{ new int };
std::unique_ptr<int[]> vec{ new int[10] };
// or
std::shared_ptr<int> ip2 = std::make_shared<int>(); // calls `new` internally
std::unique_ptr<int[]> vec2 = std::make_unique<int[]>(10);
std::cout << *ip << vec[5];
\end{minted}
%
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
low-level data structure. (Herb Sutter)
\end{guideline}
\section{Namespaces\label{sec:namespace}}
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,
// candidates: (1), (2) or (3)