C++ Introduction: Giuseppe Andronico
C++ Introduction: Giuseppe Andronico
Giuseppe Andronico
Slides come from:
By
Michael D. Adams
http://www.ece.uvic.ca/~mdadams/cppbook/
C++
created by Bjarne Stroustrup, Bell Labs
originally C with Classes, renamed as C++ in 1983
most recent specification of language in ISO/IEC 14882:2014 (informally
known as “C++14”)
procedural
loosely speaking is superset of C
directly supports object-oriented and generic programming
maintains efficiency of C
application domains: systems software, application software, device
drivers, embedded software, high-performance server and client
applications, entertainment software such as video games, native code for
Android applications
greatly influenced development of C# and Java
char c ;
char cp = nullptr;// cp is pointer to char
char* cp2 = &c; // cp2 is pointer to char
Pointer Example
code:
int i = 42;
int* p = &i;
assert(*p == 42);
Address Name
1000 42 i
1004 1000 p
References
reference is alias (i.e., nickname) for already existing object
two kinds of references:
1
lvalue reference
2
rvalue reference
lvalue reference to object of type T denoted by T& rvalue
reference to object of type T denoted by T&& initializing
reference called reference binding
lvalue and rvalue references differ in their binding properties (i.e., to what kinds
of objects reference can be bound)
in most contexts, lvalue references usually needed
rvalue references used in context of move constructors and move
assignment operators (to be discussed later)
example:
int x;
int& y = x; // y is lvalue reference to int
int&& tmp = 3; // tmp is rvalue reference to int
References Example
code:
int i = 42;
int& j = i;
assert(j == 42);
Address Name
1000 42 i, j
Addresses, Pointers, and References
References Versus Pointers
references and pointers similar in that both can be used to refer to some
other entity (e.g., object or function)
two key differences between references and pointers:
1 reference must refer to something, while pointer can have null value
(nullptr)
2 references cannot be rebound, while pointers can be changed to point to
different entity
references have cleaner syntax than pointers, since pointers must be
dereferenced upon each use (and dereference operations tend to clutter
code)
use of pointers often implies need for memory management (i.e., memory
allocation, deallocation, etc.), and memory management can introduce
numerous kinds of bugs when done incorrectly
often faced with decision of using pointer or reference in code
generally advisable to prefer use of references over use of pointers unless
compelling reason to do otherwise, such as:
must be able to handle case of referring to nothing
must be able to change entity being referred to
The auto Keyword
in various contexts, auto keyword can be used as place holder for type
in such contexts, implication is that compiler must deduce type
example:
auto i = 3; // i has type int
auto j = i; // j has type int
auto& k = i; // k has type int&
const auto& n = i; // n has type const int&
auto x = 3.14; // x has type double
very useful in generic programming (covered later) when types not always easy to
determine
1 #include <iostream>
2
3 int main() {
4 std::cout << "Enter an integer: ";
5 int x;
6 std::cin >> x;
7 if (std::cin) {
8 std::cout << "The integer entered was "
9 << x << ".\n";
10 } else {
11 std::cerr <<
12 "End-of-file reached or I/O error.\n";
13 }
14 }
I/O Manipulators
manipulators provide way to control formatting of data values written to
streams as well as parsing of data values read from streams
declarations related information for manipulators can be found in header
files: ios, iomanip, istream, and ostream
most manipulators used to control output formatting
focus here on manipulators as they pertain to output
manipulator may have immediate effect (e.g., endl), only affect next data
value output (e.g., setw), or affect all subsequent data values output (e.g.,
setprecision)
I/O Manipulators (Continued)
Name Description
setw set field width
setfill set fill character
endl insert newline and flush
flush flush stream
dec use decimal
hex use hexadecimal
oct use octal
showpos show positive sign
noshowpos do not show positive sign
left left align
right right align
fixed write floating-point values in fixed-point notation
scientific write floating-point values in scientific notation
setprecision for default notation, specify maximum number of mean-
ingful digits to display before and after decimal point; for
fixed and scientific notations, specify exactly how many
digits to display after decimal point (padding with trail- ing
zeros if necessary)
I/O Manipulators Example
1 #include <iostream >
2 #include <ios>
3 #include <iomanip >
4
5 int main() {
6 constexpr double pi = 3.1 415 92 653 5 ;
7 constexpr double big = 123456789.0 ;
8 // default notation
9 std::cout << pi << ’ ’ << big << ’\n ’;
10 // fixed-point notation
11 std::cout << std::fixed << pi << ’ ’ << big << ’\n ’;
12 // scientific notation
13 std::cout << std::scientific << pi << ’ ’ << big << ’\n ’;
14 // fixed-point notation with 7 digits after decimal point
15 std::cout << std::fixed << std::setprecision(7) << pi << ’ ’
class Widget {
private:
// ...
};
The struct Keyword
struct is class where members public by default
two code examples below are exactly equivalent:
struct Widget {
// ...
};
class Widget {
public:
// ...
};
Data Members
class example:
class Vector_2 { // Two-dimensional vector class.
public:
double x ; // The x component of the vector.
}; double y ; // The y component of the vector.
void func() {
Vector_2 v;
v .x = 1.0; // Set data member x to 1.0
} v .y = 2.0; // Set data member y to 2.0
class MyInteger {
public:
// Set the value of the integer and return the old value.
int setValue(int newValue);
private:
int value;
};
inline int MyInteger::setValue(int newValue) {
int oldValue = value;
value = newValue;
return oldValue;
}
Type Members
example:
class Point_2 { // Two-dimensional point class.
public:
typedef double Coordinate; // Coordinate type.
Coordinate x; // The x coordinate of the point.
Coordinate y; // The y coordinate of the point.
};
void func() {
Point_2 p;
// ...
Point_2::Coordinate x = p.x;
// Point_2::Coordinate same as double
}
private:
Vector* v_
};
Initializer Lists
in constructor of class, often we want to control which constructor is used to
initialize each data member
since all data members are constructed before body of constructor is
entered, this cannot be controlled inside body of constructor
to allow control over which constructors are used to initialize individual data
members, mechanism called initializer lists provided
initializer list forces specific constructors to be used to initialize individual data
members before body of constructor is entered
data members always initialized in order of declaration, regardless of order in
initializer list
Initializer List Example
class ArrayDouble { // array of doubles class
public:
ArrayDouble(); // create empty array
ArrayDouble(int size); // create array of specified size
// ...
private:
// ...
};
class Vector { // n-dimensional real vector class
public:
Vector(int size) : data_(size) {}
// force data_ to be constructed with
// ArrayDouble::ArrayDouble(int)
// ...
private:
ArrayDouble data_; // elements of vector
};
Destructors
when object reaches end of lifetime, typically some cleanup required
before object passes out of existence
destructor is member function that is automatically called when object
reaches end of lifetime in order to perform any necessary cleanup
often object may have allocated resources associated with it (e.g.,
memory, files, devices, network connections, processes/threads)
when object destroyed, must ensure that any resources associated with
object are released
destructors often serve to release resources associated with object
destructor for class T always has name T::~T̃
destructor has no return type (not even void)
destructor cannot be overloaded
destructor always takes no parameters
if no destructor is specified, destructor automatically provided that calls
destructor for each data member of class type
sometimes, automatically provided destructor will not have correct
behavior
Destructor Example
example:
class Widget {
public:
Widget(int bufferSize) { // Constructor.
// allocate some memory for buffer
bufferPtr_ = new char[bufferSize];
}
~Widget() { // Destructor.
// free memory previously allocated
delete [] bufferPtr_;
}
// copy constructor, assignment operator, ...
private:
char* bufferPtr_; // pointer to start of buffer
};
each of above functions has same general form ; that is, for some type T,
we have:
T max(T x, T y)
{return x > y ? x : y;}
would be nice if we did not have to repeatedly type, debug, test, and
maintain nearly identical code
in effect, would like code to be parameterized on type T
Function Templates
function template is family of functions parameterized by one or
parameters
each template parameter can be: non-type (e.g., integral constant), type,
template, or parameter pack (in case of variadic template)
syntax for template function has general form:
template <parameter list> function declaration
parameter list: parameters on which template function depends
function declaration: function declaration or definition
type parameter designated by class or typename keyword
template parameter designated by template keyword
template template parameter must use class keyword
non-type parameter designed by its type (e.g., bool, int)
example:
// declaration of function template
template <class T> T max(T x, T y);
// definition of function template
template <class T> T max(T x, T y)
{return x > y ? x : y;}
Function Templates (Continued)
to explicitly identify particular instance of template, use syntax:
function<parameters>
example:
for function template declaration:
template <class T> T max(T x, T y);
max<int> refers to int max(int, int)
max<double> refers to double max(double, double)
compiler only creates code for function template when it is instantiated
(i.e., used)
therefore, definition of function template must be visible in place where it
is instantiated
consequently, function template definitions usually appear in header file
template code only needs to pass basic syntax checks, unless actually
instantiated
Function Template Examples
1 // compute minimum of two values
2 template <class T>
3 T min(T x, T y) {
4 return x < y ? x : y;
5 }
6
7 // compute square of value
8 template <typename T>
9 T sqr(T x) {
10 return x * x;
11 }
12
13 // swap two values
14 template <class T>
15 void swap(T& x, T& y) {
16 T tmp = x;
17 x = y;
18 y = tmp;
19 }
20
21 // invoke function/functor multiple times
22 template <int N = 1, typename F, typename T>
23 void invoke(F func, const T& value) {
24 for (int i = 0; i < N; ++i) {
25 func(value);
26 }
27 }
Template Function Overload Resolution
overload resolution proceeds (in order) as follows:
1 look for an exact match with zero or more trivial conversions on
(nontemplate) functions; if found call it
2 look for function template from which function that can be called with exact
match with zero or more trivial conversions can be generated; if found, call it
3 try ordinary overload resolution for functions; if function found, call it;
otherwise, call is error
in each step, if more than one match found, call is ambiguous and is error
template function only used in case of exact match, unless explicitly forced
example:
template <class T>
T max(T x, T y) {return x > y ? x : y;}
void func(int i, int j, double x, double y) {
double z = max(x, y); // calls max<double>
int k = max(i, j); // calls max<int>
z = max(i, x); // ERROR: no match
z = max<double>(i, x); // calls max<double>
}
Qualified Names
1 // templates_1_1.hpp
2
3
template <class T>
4
T square(const T&);
1 // templates_1_1.cpp
2
3 #include "templates_1_1.hpp"
4
5 template <class T>
6 T square(const T& x) {
7 return x * x; 257
8 }
Motivation for Class Templates
consider almost identical complex number classes:
1 class ComplexDouble {
2 public:
3 ComplexDouble(double x = 0.0, double y = 0.0) : x_(x), y_(y) {}
4 double real() const { return x_; }
5 double imag() const { return y_; }
6 // ...
7 private:
8 double x_, y_; // real and imaginary parts
9 };
10
11 class ComplexFloat {
12 public:
13 ComplexFloat(float x = 0.0f, float y = 0.0f) : x_(x), y_(y) {}
14 float real() const { return x_; }
15 float imag() const { return y_; }
16 // ...
17 private:
18 float x_, y_; // real and imaginary parts
19 };
again, would be nice if we did not have to repeatedly type, debug, test,
and maintain nearly identical code
Class Templates
class template is family of classes parameterized on one or more
parameters
each template parameter can be: non-type (e.g., integral constant), type,
template, or parameter pack (in case of variadic template)
syntax has general form:
template <parameter list> class declaration
parameter list: parameter list for class
class declaration: class/struct declaration or definition
example:
// declaration of class template
template <class T, unsigned int size>
class MyArray;
// definition of class template
template <class T, unsigned int size>
class MyArray {
// ...
T array_[size];
};
MyArray <double, 100> x;
Class Templates (Continued)
compiler only generates code for class template when it is instantiated
(i.e., used)
since compiler only generates code for class template when it is
instantiated, definition of template must be visible at point where
instantiated
consequently, class template code usually placed in header file
template code only needs to pass basic syntax checks, unless actually
instantiated
compile errors related to class templates can often be very long and
difficult to parse (especially, when template class has parameters that are
template classes which, in turn, have parameters that are template
classes, and so on)
Class Template Example
1
// complex number class template
2
template <class T >
3
class Complex {
4 public:
5 Complex(T x = T(0), T y = T(0)) :
6 x_(x), y_(y) {}
7 T real() const {
8 return x_;
9 }
10 T imag() const {
11 return y_;
12 }
13 // ...
14 private:
15 T x_; // real part
16 T y_; // imaginary part
17 };
18
19 Complex <int> zi;
20 Complex <double> zd;
Class-Template Default Parameters
inheritance diagram:
A
B C
D E
Class Hierarchy Example
class definitions:
class Person { /* ... */ };
class Employee : public Person { /* ... */ };
class Student : public Person { /* ... */ };
class Alumnus : public Person { /* ... */ };
class Faculty : public Employee { /* ... */ };
class Staff : public Employee { /* ... */ };
class Grad : public Student { /* ... */ };
class Undergrad : public Student { /* ... */ };
inheritance diagram:
Person
during construction of object, all of its base class objects constructed first
order of construction:
1
base class objects as listed in type definition left to right
2
data members as listed in type definition top to bottom
3
constructor body
order of destruction is exact reverse of order of construction, namely:
1 destructor body
2 data members as listed in type definition bottom to top
3 base class objects as listed in type definition right to left
Order of Construction
1 #include <vector>
2 #include <string>
3
4 class Base {
5 public:
6 Base(int n) : v_(n, 0) {}
7 // ...
8 private:
9 std::vector <char> v_;
10 };
11
12 class Derived : public Base {
13 public:
14 Derived(const std::string& s) : Base(1024), s_(s)
15 { i_ = 0; }
16 // ...
17 private:
18 std::string s_;
19 int i_ ;
20 };
21
22 int main(){
23 Derived d("hello");
24 }
construction order for Derived constructor: 1) Base class object, 2) data
member s_, 3) Derived constructor body (initializes data member i_)
Hiding Base-Class Member Functions in Derived Class
can provide new versions of member functions in derived class to hide
original functions in base class
1 #include <iostream >
2
3 class Fruit {
4 public:
5 void print() const {std::cout << "fruit\n";}
6 };
7
8 class Apple : public Fruit {
9 public:
10 void print() const {std::cout << "apple\n";}
11 };
12
13 class Banana : public Fruit {
14 public:
15 void print() const {std::cout << "banana\n";}
16 };
17
18 int main() {
19 Fruit f ;
20 Apple a ;
21 Banana b ;
22 f.print(); // calls Fruit::print
23 a.print(); // calls Apple::print
24 b.print(); // calls Banana::print
25 }
Upcasting
derived-class object always has base-class subobject
given reference or pointer to derived-class object, may want to find
reference or pointer to corresponding base-class object
upcasting: converting derived-class pointer or reference to base-class
pointer or reference
upcasting allows us to treat derived-class object as base-class object
upcasting always safe in sense that cannot result in incorrect type (since
every derived-class object is also a base-class object)
in case of public inheritance, can upcast without explicit type-cast operator
in case of protected or private inheritance, cannot upcast, except with
C-style cast (which also can bypass access protection)
example:
class Base { /* ... */ };
class Derived : public Base { /* ... */ };
void func() {
Derived d;
Base* bp = &d;
}
Downcasting
downcasting: converting base-class pointer or reference to derived-class
pointer or reference
downcasting allows us to force base-class object to be treated as
derived-class object
downcasting is not always safe (since not every base-class object is
necessarily also derived-class object)
must only downcast when known that object actually has derived type
(except in case of dynamic_cast)
downcasting always requires explicit cast (static_cast for
non-polymorphic case, dynamic_cast for polymorphic case, C-style
cast for either case)
example:
class Base { /* ... (nonpolymorphic) */ };
class Derived : public Base { /* ... */ };
void func() {
Derived d;
Base* bp = &d;
Derived* dp = static_cast<Derived*>(bp);
}
Upcasting/Downcasting Example
1 class Base { /* ... (nonpolymorphic) */ };
2
3 class Derived : public Base { /* ... */ };
4
5 int main() {
6 Base b;
7 Derived d;
8 Base* bp = nullptr;
9 Derived* dp = nullptr;
10 bp = &d;
11 // OK: upcast does not require explicit cast
12 dp = bp;
13 // ERROR: downcast requires explicit cast
14 dp = static_cast<Derived*>(bp);
15 // OK: downcast with explicit cast and
16 // pointer (bp) refers to Derived object
17 Base& br = d;
18 // OK: upcast does not require explicit cast
19 Derived& dr1 = *bp;
20 // ERROR: downcast requires explicit cast
21
Derived& dr2 = *static_cast<Derived*>(bp);
22 // OK: downcast with explicit cast and
23
// object (*bp) is of Derived type
24
dp = static_cast<Derived*>(&b);
25 // BUG: pointer (&b) does not refer to Derived object
26 }
Upcasting Example
1 class Base { /* ... */ };
2
3 class Derived : public Base { /* ... */ };
4
5 void func_1(Base& b) { / ... / }
6 * *
7 void func_2(Base* b) { / ... / }
8 * *
9 int main() {
10 Base b;
11 Derived d;
12 func_1(b);
13
func_1(d); // OK: Derived& upcast to Base&
14
func_2(&b);
15
func_2(&d); // OK: Derived* upcast to Base*
16 }
Inheritance and Overloading
might want to prevent deriving from class with destructor that is not virtual
preventing derivation can sometimes also facilitate better compiler
optimization (e.g., via devirtualization)
might want to prevent derivation so that objects can be copied safely
without fear of slicing
Covariant Return Type
in some special cases, language allows relaxation of rule that type of
overriding function f must be same as type of virtual function f overrides
in particular, requirement that return type be same is relaxed
return type of derived-class function is permitted to be type derived
(directly or indirectly) from return type of base-class function
this relaxation of return type more formally known as covariant return
type
case of pointer return type: if original return type B*, return type of
overriding function may be D*, provided B is public base of D (i.e., may
return pointer to more derived type)
case of reference return type: if original return type B& (or B&&), return
type of overriding function may be D& (or D&&), provided B is public base of
D (i.e., may return reference to more derived type)
covariant return type can sometimes be exploited in order to avoid need
for type casts
Covariant Return Type Example: Cloning
1 class Base {
2 public:
3 virtual Base* clone() const {
4 return new Base(*this);
5 }
6 // ...
7 };
8
9 class Derived : public Base {
10 public:
11 // use covariant return type
12 Derived* clone() const override {
13 return new Derived(*this);
14 }
15 // ...
16 };
17
18 int main() {
19 Derived* d = new Derived;
20 Derived* d2 = d->clone();
21 // OK: return type is Derived*
22
// without covariant return type, would need cast:
23 // Derived* d2 = static_cast<Derived*>(d->clone());
24 }
Pure Virtual Functions
sometimes desirable to require derived class to override virtual function
pure virtual function: virtual function that must be overridden in every
derived class
to declare virtual function as pure, add “= 0” at end of declaration
example:
class Widget {
public:
virtual void doStuff() = 0; // pure virtual
// ...
};
pure virtual function can still be defined, although likely only useful in case
of virtual destructor
Abstract Classes
class with one or more pure virtual functions called abstract class
cannot directly instantiate objects of abstract class (can only use them as
base class objects)
class that derives from abstract class need not override all of its pure
virtual methods
class that does not override all pure virtual methods of abstract base class will
also be abstract
most commonly, abstract classes have no state (i.e., data members) and used
to provide interfaces, which can be inherited by other classes
if class has no pure virtual functions and abstract class is desired, can
make destructor pure virtual (but must provide definition of destructor
since invoked by derived classes)
Abstract Class Example
1 #include <cmath>
2
3 class Shape {
4 public:
5 virtual bool isPolygon() const = 0;
6 virtual float area() const = 0;
7 virtual S̃hape() {};
8 };
9
10 class Rectangle : public Shape {
11 public:
12 Rectangle(float w, float h) : w_(w), h_(h) {}
13
bool isPolygon() const override {return true;}
14
float area() const override {return w_ * h_;}
15
private:
16 float w_ ; // width of rectangle
17 float h_ ; // height of rectangle
18 };
19
20
class Circle : public Shape {
21
public:
22 Circle(float r) : r_(r) {}
23
float area() const override {return M_PI * r_ * r_;}
24 bool isPolygon() const override {return false;}
25 private:
26 float r_; // radius of circle
27 };
Pure Virtual Destructor
Example
1 class Abstract {
2 public:
3 virtual Ãbstract() = 0; // pure virtual destructor
4 // ... (no other virtual functions)
5 };
6
7 inline Abstract::Ãbstract()
8 { /* possibly empty */ }
The dynamic_cast Operator
often need to upcast and downcast (as well as cast sideways) in
inheritance hierarchy
dynamic_cast can be used to safely perform type conversions on
pointers and references to classes
syntax: dynamic_cast<T>(expr)
types involved must be polymorphic (i.e., have at least one virtual
function)
inspects run-time information about types to determine whether cast can
be safely performed
if conversion is valid (i.e., expr can validly be cast to T), casts expr to type
T and returns result
if conversion is not valid, cast fails
if expr is of pointer type, nullptr is returned upon failure
if expr is of reference type, std::bad_cast exception is thrown upon
failure (where exceptions are discussed later)
dynamic_cast Example
1 #include <cassert>
2
3 class Base {
4 public:
5 virtual void doStuff() { /* ... */ };
6 // ...
7 };
8
9 class Derived1 : public Base { /* ... */ };
10 class Derived2 : public Base { /* ... */ };
11
12 bool isDerived1(Base& b) {
13 return dynamic_cast<Derived1*>(&b) != nullptr;
14 }
15
16 int main() {
17 Base b ;
18 Derived1 d1;
19 Derived2 d2;
20 assert(isDerived1(b) == false);
21 assert(isDerived1(d1) == true);
22 assert(isDerived1(d2) == false);
23 }
Cost of Run-Time Polymorphism
typically, run-time polymorphism does not come without run-time cost in
terms of both time and memory
in some contexts, cost can be significant
typically, virtual functions implemented using virtual function table
each polymorphic class has virtual function table containing pointers to all
virtual functions for class
each polymorphic class object has pointer to virtual function table
memory cost to store virtual function table and pointer to table in each
polymorphic object
in most cases, impossible for compiler to inline virtual function calls since
function to be called cannot be known until run time
each virtual function call is made through pointer, which adds overhead
Multiple Inheritance
language allows derived class to inherit from more than one base class
multiple inheritance (MI): deriving from more than one base class
although multiple inheritance not best solution for most problems, does
have some compelling use cases
one compelling use case is for inheriting interfaces by deriving from
abstract base classes with no data members
when misused, multiple inheritance can lead to very convoluted code in
multiple inheritance contexts, ambiguities in naming can arise
for example, if class Derived inherits from classes Base1 and Base2, each of
which have member called x, name x can be ambiguous in some contexts
scope resolution operator can be used to resolve ambiguous names
C++ Standard Library
Diagnostics Library
Header File Description
cassert assertions (e.g., assert)
stdexcept predefined exception types (e.g.,
invalid_argument, domain_error,
out_of_range)
Commonly-Used Header Files (Continued 1)
General-Utilities Library
Header File Description
utility basic function and class templates (e.g., swap,
move, pair)
memory memory management (e.g.,
unique_ptr,
shared_ptr, addressof)
functional functors (e.g., less, greater)
type_traits type traits (e.g., is_integral, is_reference)
Strings Library
Header File Description
string C++ string classes (e.g., string)
cstring C-style strings, similar to string.hfrom C (e.g., strlen)
cctype character classification, similar to ctype.h from C (e.g., isdigit,
isalpha)
Commonly-Used Header Files (Continued 2)
Numerics Library
Header File Description
cmath C math library, similar to math.h from C (e.g., sin, cos)
complex complex numbers (e.g., complex)
random random number generation
(e.g.,
uniform_int_distribution,
uniform_real_distribution,
normal_distribution)
Commonly-Used Header Files (Continued 4)
I/O Library
Header File Description
iostream iostream objects (e.g., cin, cout, cerr)
istream input streams (e.g., istream)
ostream output streams (e.g., ostream)
ios base classes and other declarations for
streams (e.g., ios_base, hex, fixed)
fstream file streams (e.g., fstream)
sstream string streams (e.g., stringstream)
iomanip manipulators (e.g., setw, setprecision)
Regular-Expressions Library
Header File Description
regexp regular expressions (e.g., basic_regex)
Commonly-Used Header Files (Continued 5)
1 containers
2 iterators
3 algorithms
Container Adapters
Name Description
stack stack
queue FIFO queue
priority_que priority queue
ue
Associative Containers
Ordered Associative Containers
Name Description
set collection of unique keys, sorted by key
map collection of key-value pairs, sorted by key, keys are unique
multise collection of keys, sorted by key, duplicate keys allowed
t
multima collection of key-value pairs, sorted by key, duplicate keys al-
p lowed
Unordered Associative Containers
Name Description
unordered_set collection of unique keys, hashed by key
unordered_map collection of key-value pairs, hashed by key, keys are
unique
unordered_multis collection of keys, hashed by key, duplicate keys al-
et lowed)
unordered_multim collection of key-value pairs, hashed by key, duplicate
ap keys allowed
Typical Sequence Container Member Functions
some member functions typically provided by sequence container classes
listed below (where T denotes name of container class)
Function Description
T() create empty container (default constructor)
T(const T&) copy container (copy constructor)
T(T&&) move container (move constructor)
T̃ destroy container (including its elements)
empty test if container empty
size get number of elements in container
push_back insert element at end of container
clear remove all elements from container
operator= assign all elements of one container to other
operator[] access element in container
Container Example
1
#include <iostream >
2
#include <vector >
3
4
int main() {
5
std::vector <int>
values ;
6
7
// append elements with values 0 to 9
8 for (int i = 0; i < 10; ++i) {
9 values.push_back(i);
10 }
11
12 // print each element followed by space
13 for (int i = 0; i < values.size(); ++i) {
14 std::cout << values[i] << ’ ’;
15 }
16 std::cout << ’\n’;
17 }
18
19 /* This program produces the following output:
20 0 1 2 3 4 5 6 7 8 9
21 */
The vector Class Template
dynamically-sized one-dimensional array type, where type of array
elements and storage allocator specified by template parameters
vector declared as:
template <class T, class Allocator = allocator <T>>
class vector;
Iterators
Member Name Description
begin return iterator to beginning
end return iterator to end
cbegin return const iterator to beginning
cend return const iterator to end
rbegin return reverse iterator to beginning
rend return reverse iterator to end
crbegin return const reverse iterator to beginning
crend return const reverse iterator to end
Member Functions (Continued 1)
Capacity
Member Name Description
empty test if vector is empty
size return size
max_size return maximum size
capacity return allocated storage capacity
reserve request change in capacity
shrink_to_fit shrink to fit
Element Access
Member Name Description
operator[] access element (no bounds checking)
at access element (with bounds checking)
front access first element
back access last element
data return pointer to start of element data
Member Functions (Continued 2)
Modifiers
Member Name Description
clear clear content
assign assign vector content
insert insert elements
emplace insert element, constructing in place
push_back add element at end
emplace_bac insert element at end, constructing in place
k
erase erase elements
pop_back delete last element
resize change size
swap swap content of two vectors
Allocator
Member Name Description
get_allocator get allocator used by vector
Invalidation of References, Iterators,
and Pointers
capacity: total number of elements that vector could hold without
requiring reallocation of memory
any operation that causes reallocation of memory used to hold elements
of vector invalidates all iterators, references, and pointers referring to
elements in vector
any operation that changes capacity of vector causes reallocation of
memory
any operation that adds or deletes elements can invalidate references,
iterators, and pointers
operations that can potentially invalidate references, iterators, and
pointers to elements in vector include:
insert, erase, push_back, pop_back, emplace, emplace_back,
resize, reserve, operator=, assign, clear, shrink_to_fit, swap
(past-the-end iterator only)
Iterator Invalidation Example
start denotes pointer to first element in array holding vector elements
i is iterator for vector (e.g., vector<T>::const_iterator, vector<T>::iterator)
initial vector with three elements and capacity of three:
push_back(d) results in new larger array being allocated, contents of old array
copied to new one, and then new element added:
program output:
1 2 3
4 5 6
0 0 0 0 0 0 0 0 0 0
Example with vector and auto
vector<int>s;
s.push_back(11);
s.push_back(22);
s.push_back(33);
s.push_back(55);
for (vector<int>::iterator it = s.begin(); it!=s.end(); it++) {
cout << *it << endl;
}
for (auto& it : s) {
cout << it << endl;
}
The map Class Template
sorted associative container that contains key-value pairs with unique
keys. Keys are sorted by using the comparison function Compare
map declared as:
template<class Key, class T, class Compare =
std::less<Key>, class Allocator =
std::allocator<std::pair<const Key, T> >
> class map;
Key: typeof keyin map
T: type of elements in map
Compare: object to compare keys for sorting
Allocator: type of object used to handle storage allocation (unless
custom storage allocator needed, use default)
what follows only intended to provide overview of map
for additional details on map, see:
http://www.cplusplus.com/reference/map/map/
http://en.cppreference.com/w/cpp/container/map
Member Types
Member Type Description
key_type The first template parameter (Key)
mapped_type The second template parameter (T)
value_type pair<const key_type,mapped_type>
key_compare The third template parameter (Compare)
value_compare Nested function class to compare elements
allocator_type The fourth template parameter (Alloc)
reference value_type&
const_reference const value_type&
pointer allocator_traits<allocator_type>::pointer
const_pointer allocator_traits<allocator_type>::const_pointer
const_reverse_iterator
const reverse iterator
typereverse_iterator<const_iterator>
Member Functions
Construction, Destruction, and Assignment
Member Name Description
constructor construct map
destructor destruct map
operator= copy container content
Iterators
Member Name Description
begin Return iterator to beginning
end Return iterator to end
rbegin Return reverse iterator to reverse beginning
rend Return reverse iterator to reverse end
cbegin Return const_iterator to beginning
cend Return const_iterator to end
crbegin Return const_reverse_iterator to reverse beginning
crend Return const_reverse_iterator to reverse end
Member Functions (Continued 1)
Capacity
Member Name Description
empty checks whether the container is empty
size returns the number of elements
returns the maximum possible number of
max_size elements
Element Access
Member Name Description
access specified element with bounds
at checking
operator[] access specified element
Member Functions (Continued 2)
Modifiers
Member Name Description
clear clears the contents
insert inserts elements or nodes
inserts an element or assigns to the current
insert_or_assign element if the key already exists
emplace constructs element in-place
emplace_hint constructs elements in-place using a hint
inserts in-place if the key does not exist, does
try_emplace nothing if the key exists
erase erases elements
swap swaps the contents
extract extracts nodes from the container
merge splices nodes from another container
Allocator
Member Name Description
get_allocator returns the associated allocator
map Example: Constructors
// Default constructor
std::map <std::string, double> map1;
// empty map
map1[‘something’] = 69;
map1[‘anything’] = 199;
// Range constructor
std::map<std::string, int> iter(map1.find("anything"),
map1.end());
// Copy constructor
std::map<std::string, int> copied(map1);
map Example: Iterators
#include <iostream>
#include <map>
int main() {
std::map<int, float> num_map;
num_map[4] = 4.13;
num_map[9] = 9.24;
num_map[1] = 1.09;
// calls a_map.begin() and a_map.end()
for (auto it = num_map.begin(); it != num_map.end(); ++it) {
std::cout << it->first << ", " << it->second << '\n';
}
}
C++
map Example
#include <string>
#include <iostream>
#include <map>
int main()
{
std::map<std::string,int> my_map;
my_map["x"] = 11;
my_map["y"] = 23;
auto it = my_map.find("x");
if (it != my_map.end()) std::cout << "x: " << it->second << "\n";
it = my_map.find("z");
if (it != my_map.end()) std::cout << "z1: " << it->second << "\n";
it = my_map.find("z");
if (it != my_map.end()) std::cout << "z2: " << it->second << "\n";
}
Output:
x: 11
z2: 0
map Example: Emplace
#include <iostream>
#include <utility>
#include <string>
#include <map>
int main()
{
std::map<std::string, std::string> m;