10 STL

Werbung
Programmieren in C++
Standardbibliothek (STL)
Inhalt









C++ Geschichte
Standardbibliothek in der Übersicht
Hilfsfunktionen und Hilfsklassen
Relationale Operatoren
Funktionales Programmieren
Container
Iteratoren
Algorithmen
Speicherverwaltung
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-2
C++: Die Anfänge

1979
•
•

„C with Classes“ wird von Bjarne Stroustrup in den AT&T Bell Laboratories
entwickelt
„C with Classes“ erweitert C um ein Klassenkonzept, welches sich an Simula-67
anlehnt
1983
•
•
Umbenennung in C++
viele Erweiterungen



virtuelle Funktionen, Überladen von Funktionsnamen und Operatoren, Referenzen,
Konstanten, änderbare Freispeicherverwaltung und eine verbesserte Typüberprüfung
1985
•
1. C++ Referenzversion (noch nicht standardisiert)
1989
•
•
2. Version (noch nicht standardisiert)
Erweiterungen

Mehrfachvererbung, abstrakte Klassen, statische Elementfunktionen, konstante
Elementfunktionen und die Erweiterung des Schutzmodells um protected
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-3
C++: Der Weg zum ISO/IEC Standard

1990-1998
•
weitere Erweiterungen

•
•




Templates, Ausnahmen, Namensräume, neuartige Typumwandlungen und boolesche
Typen
Erweiterung der C-Standardbibliothek um Datenströme und um die Standard
Template Library (STL)
Standardisierungsverfahren
1998
•
Normung der endgültigen Fassung der Sprache C++
(ISO/IEC 14882:1998)
2003
•
Nachbesserung der Norm von 1998 (ISO/IEC 14882:2003)
2005
•
Technical Report 1 (TR1): Erweiterungen, die 2003 nicht standardisiert wurden
2011
•
Einführung des neuen C++-Standards  C++11
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-4
C++ Standardbibliothek


Erweiterbares Framework bestehend aus
•
•
•
•
•
•
•
•
•
•
•
Ausnahmebehandlung (Exceptions)
Strings
Container
(numerische) Algorithmen
komplexe Zahlen
Anpassungen an nationale Zeichensätze
Ein- und Ausgabe
reguläre Ausdrücke
Zufallszahlen und Wahrscheinlichkeitsverteilungen
Threads und Synchronisationsprimitive
…
Grundlage und Dokumentation
•
•
•
Standard Template Library (STL)
STL Programmierhandbuch von SGI
C++ und STL Referenz
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-5
Schwerpunkte
C++-Headers
Hilfsfunktionen und
-klassen
<utility> <functional>
Container
<bitset> <deque> <forward_list> <list> <map>
<queue> <set> <stack> <vector>
Iteratoren
<iterator>
Algorithmen
<algorithm>
Ein- /Ausgabe
<fstream> <iomanip> <ios> <iosfwd> <iostream>
<istream> <ostream> <sstream> <streambuf>
Numerisches
<complex> <limits> <numerics> <valarray>
Fehlerbehandlung
<exception> <stdexcept> <system_error>
String
<string>
Speicher
<memory> <new>
Laufzeittyperkennung
<typeinfo>
Nationale Zeichensätze
<locale>
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-6
Schwerpunkte
neue C++11-Headers
Parallelität
<thread> <future>
Reguläre Ausdrücke
<regex>
Rechnen mit Einheiten
<ratio>
Rechnen mit Zeiteinheiten <clock>
Wahrscheinlichkeitsverteilungen
<random>
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-7
STL: Standard Template Library



Entwicklung
•
•
entwickelt von Alexander Stepanov et al. (1979-1994) bei HP
basiert auf SGI's STL, ist aber nicht identisch
Design-Regeln
•
•
Polymorphismus zur Kompilationszeit (templates)
STL-Container eignen sich schlecht als Basisklassen, weil die
Destruktoren nicht virtual sind
Bemerkung
•
•
STL ist Teil der Standardbibliothek, der sich aber nicht mehr sauber
vom Rest trennen lässt
für C++11 komplett überarbeitet und erweitert worden
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-8
Hilfsfunktionen und Hilfsklassen

Klasse tuple
•
erlaubt die Kombination heterogener Werte
tuple<int, double, string> tup(1, 2.2, "drei");
auto val = get<0>(tup);
get<1>(tup) = 1.5;
size_t s = tuple_size<decltype(tup)>::value; // Anzahl Elemente im Tupel

Funktion swap()
•
•
vertauscht die Werte zweier Variablen vom gleichen Typ
Originalcode
template<class _Ty> inline void swap(_Ty& _Left, _Ty& _Right) {
if (&_Left != &_Right) {
_Ty _Tmp = _Left;
_Left = _Right;
_Right = _Tmp;
}
}
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-9
Relationale Operatoren



Voraussetzung für die Anwendung
•
die Klasse stellt die Operatoren == und < zur Verfügung
Nutzen
•
•
•
•
•
die Realisierung der Operatoren
a != b  ! (a == b)
a>b  b<a
a ≤ b  ! (b < a)
a ≥ b  ! (a < b)
Code-Ausschnitt
namespace rel_ops {
template<class T> bool operator!=(const T& x, const T& y) {
return !(x == y);
}
}
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-10
Funktionale Programmierung



C++ ist ein Multi-Paradigmen-Sprache
•
•
•
imperatives Programmieren
objektorientiertes Programmieren
funktionales Programmieren
Funktionale Programmierung
•
•
•
•
Programme sind Funktionen
Objekte sind unveränderlich (immutable)
Funktionen produzieren neue Objekte
Funktionen sind selber auch Objekte
Funktionale Programmiersprachen
•
•
•
•
LISP
Haskell
F#
Scala
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-11
Funktionale Elemente von C++






Funktion
•
•
•
typisierte Parameterlisten
variable Anzahl Parameter
global oder als Methode einer (unveränderbaren) Klasse
Funktor
•
Instanz einer Klassen, welche den Funktionsoperator operator()(…) überlädt
Funktionszeiger (out in C++11)
•
Adresse auf eine Funktion
Methodenzeiger
•
eine schon an eine Instanz gebundene Methode
Lambda (C++11)
•
eine anonyme Funktion, ein so genannter Lambda-Ausdruck, welcher dort
definiert werden kann (aber nicht muss), wo er eingesetzt wird
Funktionsobjekt
•
Instanz der Klasse functional aus dem Header <functional>
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-12
Funktoren


Objekte als Funktionen
•
•
•
die Aufgabe einer Funktion wird von einem Objekt übernommen
Überladen des Funktionsoperators operator()(…)
Anwenden des Funktionsoperators entspricht dem Aufrufen des
Funktionsoperators für das entsprechende Objekt
Beispiel
enum Modus { Rad, Deg, Gon };
class Sinus {
Modus m_mode;
public:
Sinus(Modus mode = Rad) : m_mode(mode) {}
double operator()(double arg) {
switch(m_mode) {
case Rad: return sin(arg);
case Deg: return sin(arg/180.0*M_PI);
case Gon: return sin(arg/200.0*M_PI);
} } };
Einsatz
int main() {
Sinus sinrad;
Sinus sindeg(Deg);
cout << sinrad(M_PI/4);
cout << sindeg(45.0);
}
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-13
Lambda (C++11)






Syntax
•
Zugriffsdeklaration Parameterliste [Rückgabetyp] Funktionskörper
Beispiel
•
[bias] (int x, int y) -> int { return bias + x + y; }
Zugriffsdeklaration
•
gibt in eckigen Klammern an, auf welche Variablen der Umgebung
zugegriffen werden kann
Parameterliste
•
Deklaration der Funktionsargumente analog zu normalen Funktionen
Rückgabetyp
•
die Angabe des Rückgabetyps ist optional (kann vom Compiler selber
ermittelt werden), darf auch void sein (Prozedur)
Funktionskörper
•
ein gewöhnlicher Funktionskörper mit oder ohne return-Anweisung
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-14
Lambda Zugriffsdeklaration (C++11)

Hintergrund
•
•
•

dort wo der Lambda-Ausdruck definiert wird, existiert eine lokale Umgebung
bestehend aus lokalen Variablen und Instanzvariablen
in der Zugriffsdeklaration wird angegeben, auf welche Variablen der
Umgebung zugegriffen wird und ob der Zugriff by-value oder by-reference
stattfinden soll
auf statische und globale Variablen kann immer zugegriffen werden, auch
ohne Angabe in der Zugriffsdeklaration
Beispiele
•
•
•
•
•
•
[bias]
[&bias]
[=]
[&]
[=, &bias]
[factor, &bias]
auf die Variable bias wird by-value zugegriffen
auf die Variable bias wird by-reference zugegriffen
auf alle Variablen der Umgebung wird by-value zugegriffen
auf alle Variablen der Umgebung wird by-ref. zugegriffen
nur auf bias wird by-ref. zugegriffen, sonst by-value
auf factor wird by-value und auf bias by-ref. zugegriffen
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-15
Lambda hinter der Kulisse (C++11)
void fLambda() {
int notUsed = 3, byval = 4, byref = 5;
auto op = [byval, &byref](int i) { ++byref; return i + byval + byref; };
cout << op(10) << endl;
}
void fFunctor() {
int notUsed = 3, byval = 4, byref = 5;
struct Op {
int m_val;
int& m_ref;
Op(int val, int& ref) : m_val{val), m_ref{ref} {}
int operator()(int i) const {++m_ref; return i + m_val + m_ref; }
} op{byval, byref};
cout << op(10) << endl;
}
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-16
Funktionsobjekte im Einsatz (C++11)
#include <functional>
main() {
function<float (float a, int x)> func; // Deklaration des Funktionsobjekts
vector<int> v{1, 2, 3, 4, 5};
func = …
// Definition des Funktionsobjekts
// (Funktor, Funktionszeiger, Methodenzeiger, Lambda)
// siehe nächste Folie
// Einsatz des Funktionsobjekts in einem Algorithmus
float r = accumulate(v.cbegin(), v.cend(), 1.0f, func);
}
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-17
Verschiedene Funktionsobjekte
Funktor, Funktionszeiger
Methodenzeiger, Lambda
struct Funktor {
float m_div;
Funktor(float f) : m_div(f) {}
float operator()(float a, int x) const {
return a + x/m_div;
}
};
---func = Funktor(2.0f);
---float foo(float a, int x) { return a + x/2.0f;}
func = &foo;
struct C {
float m_div;
C(float f) : m_div(f) {}
float meth(float a, int x) const {
return a + x/m_div;
}
};
---C c(2.0f);
func = bind(&C::meth, &c, _1, _2);
---func = [](float a, int x) { return a + x/2.0f; }
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-18
Container (1)





Bitvektoren fixer Länge
•
bitset: <bitset>
Halbdynamische Container
•
vector und vector<bool>: <vector>
Listen
•
•
•
double ended queue: <deque>
list (doubly-linked): <list>
forward_list (singly-linked, C++11): <forward_list>
Geordnete Mengen
•
•
set (die Schlüssel werden sortiert verwaltet): <set>
multiset (Mehrfacheinträge sind erlaubt): <set>
Geordnete Maps
•
•
map: <map>
multimap (Schlüssel müssen nicht eindeutig sein): <map>
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-19
Container (2)



Ungeordnete Mengen (Hash-Sets, C++11)
•
•
unordered_set (die Schlüssel werden sortiert verwaltet):
<unordered_set>
unordered_multiset (Mehrfacheinträge sind erlaubt): <unordered_set>
Ungeordnete Maps (Hash-Maps, C++11)
•
•
unordered_map: <unordered_map>
unordered_multimap (Schlüssel müssen nicht eindeutig sein):
<unordered_map>
Container-Interfaces
•
•
•
verwendet einen Container (z.B., vector, deque oder list) als
Datenbehälter
bietet spezielle Datenzugriffe an
Interfaces



stack (LIFO): <stack>
queue (FIFO): <queue>
priority queue: <queue>
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-20
Container: Datentypen und Methoden


Datentypen (angeboten/erforderlich) für Container X<T>
•
•
•
•
•
•
•
X::value_type
X::reference
X::const_reference
X::iterator
X::const_iterator
X::difference_type
X::size_type
Container-Element, entspricht T
Referenz auf Container-Element
dito, aber nur lesend verwendbar
Iterator
dito, aber nur lesend verwendbar
vorzeichenbehafteter integraler Typ
vorzeichenloser integraler Typ für Grössenangaben
Methoden (nicht vollständig)
•
•
•
•
•
•
•
Standard-, Kopier- und Verschiebekonstruktor, Destruktor
Iteratoren (lesend und schreibend): begin() und end()
Iteratoren (nur lesend): cbegin() und cend()
Grössenangaben: max_size(), size(), empty()
Zuweisungsoperator und Verschiebezuweisungsoperator
Relationale Operatoren
Vertauschen: swap(X&)
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-21
Iteratoren
begin()

Konzept
•
•
•
•
•

end()
Iterator: verallgemeinerter Zeiger, welcher auf ein Element des Containers zeigt
begin() und cbegin() liefern einen Zeiger, der aufs erste Element zeigt
end() und cend() liefern einen Zeiger, auf ein fiktives Element unmittelbar
nachfolgend dem letzten Element
Inkrementierer ++ springt zum nächsten Element
Dereferenzierer * ermöglicht Zugriff aufs Element
Untypisches Beispiel
template<class T> void printAll(const T& c) {
T::const_iterator it = c.cbegin(), end = c.cend();
while(it != end) {
cout << *it++ << ' ';
}
cout << endl;
}
vector<int> v(10);
for(size_t i = 0; i < v.size(); i++) {
v[i] = i;
}
printAll(v);
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-22
Freie Methoden begin() und end()

Variante des gleichen Beispiels
template<class T> void printAll(const T& c) {
for(auto it = begin(c); it != end(c); ++it) {
cout << *it << ' ';
}
cout << endl;
}

Verwendung des Range-For
template<class T> void printAll(const T& c) {
for(auto& val : c) {
cout << val << ' ';
}
cout << endl;
}
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-23
Iterator-Kategorien
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-24
Verschiedene Spezialiteratoren


Move-Iteratoren
•
die Daten werden verschoben anstatt kopiert
Insert-Iteratoren
•
•
mit einem normalen Iterator kann auf Elemente lesend/schreibend
zugegriffen werden
ein Insert-Iterator erlaubt das einfügen in einen Container





front_insert_iterator
back_insert_iterator; Beispiel: back_insert_iterator<list<double>> bIt(l);
insert_iterator (einfügen an spezifizierter Position)
Reverse-Iteratoren
•
•
läuft rückwärts von rbegin() bis rend()
++-Operator wird zum Iterieren verwendet
Stream-Iteratoren
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-25
Algorithmen

Grundsätze
•
•
•
•

alle im Header <algorithm> vorhandenen Algorithmen sind unabhängig
von einer konkreten Container-Implementierung
enthält eine Container-Implementierung einen gleichnamigen
Algorithmus wie im Header <algorithm>, so soll die spezielle Version
des Containers verwendet werden (höhere Effizienz)
die Algorithmen greifen über Iteratoren auf die Elemente des Containers
zu
wird ein First- und ein Last-Iterator verlangt, so ist damit das halboffene
Intervall [First, Last) gemeint
Beispiel
vector<int>::iterator pos;
pos = find_if(v.begin(), v.end(), bind2nd(equal_to<int>(), 25));
cout << *pos << endl;

Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-26
Algorithmen: Übersicht (1)






Suchen eines Elementes
•
•
find, find_if, find_end, find_first_of, adjacent_find
nth_element
Suchen einer Sequenz
•
search, search_n
Zählen von Elementen, die ein Prädikat erfüllen
•
count
Vergleichen zweier Elemente
•
min, max, min_element, max_element
Vergleichen zweier Sequenzen
•
lexicographical_compare
Vergleichen zweier Container
•
mismatch, equal
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-27
Algorithmen: Übersicht (2)






Kopieren der Elemente eine Quellbereichs in einen Zielbereich
•
copy, copy_backward
Vertauschen von Elementen oder Containern
•
swap, iter_swap, swap_ranges
Einfüllen von Sequenzen
•
fill, fill_n, generate, generate_n
Ersetzen von Elementen
•
replace, replace_if, replace_copy, replace_copy_if
Entfernen
•
•
remove, remove_if, remove_copy, remove_copy_if
unique, unique_copy
Transformieren (Kopieren und dabei Modifizieren)
•
transform
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-28
Algorithmen: Übersicht (3)






Reihenfolge verändern
•
•
reverse, reverse_copy, rotate, rotate_copy, random_shuffle
partition, sort, partial_sort
Permutationen
•
prev_permutation, next_permutation
Suchen in sortierten Sequenzen
•
•
binary_search, lower_bound, upper_bound
equal_range
Mischen zweier sortierter Sequenzen
•
merge, inplace_merge
Mengenoperationen auf sortierten Strukturen
•
includes, set_union, set_intersection, set_difference,
set_symmetric_difference
Heap-Algorithmen
•
pop_heap, push_heap, make_heap, sort_heap
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-29
Speichermanagement

Header <new>
•
•
•
enthält die Operatoren new, new[], delete und delete[]
Fehlerbehandlung bei der Speicherallokation:

Verhinderung einer Exception bei der Speicherallokation


std::bad_alloc Exception wird geworfen
int *data = new(std::nothrow) data[1000];
Header <memory>
•
•
•
Speicherverwaltung
erlaubt Erweiterung bzw. Anpassung der Standardspeicherverwaltung
(z.B. durch Garbage Collection)
Smart Pointers (unique_ptr, shared_ptr, weak_ptr)

auto_ptr ist veraltet
Prof. Dr. C. Stamm – Programmieren in C++, FS 13
10-30
Herunterladen