C++ Standard Template Library Ausgewählte Kapitel aus Softwaretechnologie Robert Fritz roggi@sbox.tugraz.at C++ Standard Template Library (STL) p.1/41
Inhalt Einführung Generisches Programmieren Aufbau der C++ Standard Template Library Container (Template Klassen) Sequenzen (vector, list,...) Adaptierte Sequenzen (stack, queue,...) Assoziative Container (set, map,...) Iteratoren Algorithmen (Template Funktionen) C++ Standard Template Library (STL) p.2/41
Einführung Schöpfer der STL: Alex Stepanov und Meng Lee (Forschungsprojekt über generische Algorithmen. Vorschläge wurden weitesgehend vom ANSI-Komitee übernommen wurden) Verallgemeinerung von Datenstrukturen und Algorithmen C++ Templates: allgemeines Template<T>, T ist ein verallgemeinerter Parameter Typ Bei der Instantiierung wird der allgemeine Typ durch speziellen Typ ersetzt - Objekte, Pointer, Standardtypen (int, char,...) Änderungen leicht möglich Algorithmen sind globale Funktionen (OOP?) C++ stellt zwei Arten von Templates zur Verfügung: Template Klassen - Container (Listen, Sets, Vektoren,...) Template Funktionen - Algorithmen (Sortier -und Suchfunktionen,...) C++ Standard Template Library (STL) p.3/41
Generisches Programmieren Algorithmen werden mit minimalem Wissen über die Datenabstraktion geschrieben und vice versa. Verallgemeinerung von Algorithmen ohne die Effizient zu verlieren. Gleiche Effizienz von spezialisiertem Algorithmus und originalem Algorithmus. Verschiedene Verallgemeinerungsstufen (automatische Auswahl des effizientesten Algorithmus) Mehrere Algorithmen für den selben Zweck auf dem selben Abstraktionslevel. C++ Standard Template Library (STL) p.4/41
Verwendung von Template Klassen 1/2 Deklaration und Definition der Template Klassen müssen in einer Header Datei erfolgen. template <class T> class Stack { public: Stack(int = 10) ; ~Stack() { delete [] stackptr ; } int push(const T&); int pop(t&) ; int isempty()const { return top == -1 ; } int isfull() const { return top == size - 1 ; } private: int size ; // number of elements on Stack. int top ; T* stackptr ; }; C++ Standard Template Library (STL) p.5/41
Verwendung von Template Klassen 2/2 #include <iostream> #include "stack.h" using namespace std ; void main() { typedef Stack<float> FloatStack ; typedef Stack<int> IntStack ; FloatStack fs(5) ; float f = 1.1 ; cout << "Pushing elements onto fs" << endl ; while (fs.push(f)) { cout << f << ; f += 1.1 ; } cout << endl << "Stack Full." << endl } //... C++ Standard Template Library (STL) p.6/41
Verwendung von Template Funktionen template <class T> T max(t a, T b) { return a > b? a : b ; } void main() { } cout << "max(10, 15) = " << max(10, 15) << endl ; cout << "max( k, s ) = " << max( k, s ) << endl ; cout << "max(10.1, 15.2) = " << max(10.1, 15.2) << endl ; C++ Standard Template Library (STL) p.7/41
C++ Standard Template Library Grundproblem: n verschiedene Datentypen (int, double, void *,...) m verschiedene Container (vector<>, list<>,...) k Algorithmen (sort, unique,...) Herkömmliche Programmierung: n*m*k verschiedene Implementierungen Templates erlauben, die Algorithmen für beliebige Typen zu implementieren. Voraussetzung ist, dass alle Container eine gewisse Minimalschnittstelle unterstützen. Diese Minimalanforderungen an die Container sind in verschiedene Gruppen gegliedert. Nicht alle Algorithmen arbeiten mit allen Container zusammen. C++ Standard Template Library (STL) p.8/41
C++ Standard Template Library Die Standard Template Library ist Bestandteil der C++ Standardbibliothek. Alle Container und Algorithmen sind im Standard Namespace definiert. using namspace std; oder std::vector<int> vec; C++ Standard Template Library (STL) p.9/41
Allgemeine Ziele der STL Generisch Keine Festlegung auf konkrete Typen Effizient Nicht langsamer als handgeschriebener Code Vollständig Behandelte Aspekte werden vollständig abgedeckt Primitiv Keine Bündelung unterschiedlicher Aspekte Typsicher Erhalt der statischen Typisierung Erweiterbar Applikationsspezifische Spezialisierung mit vertretbarem Aufwand C++ Standard Template Library (STL) p.10/41
STL: Beziehungen zwischen den Konzepten C++ Standard Template Library (STL) p.11/41
STL Iteratoren Iteratoren sind fundamental, um Container und Algorithmen verwenden zu können Traversierung von Containern nur mit Iteratoren möglich Jeder Container stellt je nach Datenstruktur die geeigneten Iteratoren bereit Vorwärtsiteratoren, Bidirektionale Iteratoren,... Iterator: Verallgemeinerung eines Pointers *iter;... Iteratoren halten bestimmte Werte Ein Paar von Iteratoren kann einen Bereich von Werten abdecken begin(); end(); Pointerarithmetik ist übertragbar auf Iteratoren iter++, iter += 5 v.end kann nicht dereferenziert werden, enthält kein Element C++ Standard Template Library (STL) p.12/41
Pointer: STL Iteratoren: Verallgemeinerung int* find(int* array, int n, int x) { int* p = array; for (int i = 0; i < n; i++) { if (*p == x) return p; // gefunden p++; } return 0; // nicht gefunden } Iterator: template<typename T, typename P> P find(p first, P past_end, T x) { while (first!= past_end && *first!= x) first++; return first; // Ergebnis } C++ Standard Template Library (STL) p.13/41
STL Iteratoren: Input Iterator Nur lesender Zugriff: x = *iter; Nächstes Element: iter++; ++iter; Vergleichen: iter1 == iter2; iter1!= iter2 Erzeugen: Copy-Konstruktor, Assignment-Operator Beispiel: template <class InputIterator, class T> InputIterator find (InputIterator first, InputIterator last, const T& value) { while (first!= last && *first!= value) ++first; return first; } C++ Standard Template Library (STL) p.14/41
STL Iteratoren: Output Iterator Nur schreibender Zurgriff: *iter = x Vergleichsoperator ist nicht implementiert Lesender Zugriff ist nicht möglich Beispiel: template <class InputIterator, class OutputIterator> OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result) { while (first!= last) *result++ = *first++; return result; } C++ Standard Template Library (STL) p.15/41
STL Iteratoren: Kategorien Vorwärts Iterator: Verschmelzung von Input und Output Iterator Lesender Zugriff: x = *iter; Schreibender Zugriff: *iter = x; Bidirektionaler Iterator: Wie Vorwärts Iterator Nächstes Element vorwärts: iter++; ++iter; Nächstes Element rückwärts: iter ; iter; C++ Standard Template Library (STL) p.16/41
STL Iteratoren: Kategorien Random Access Iterator (vector, deque): Wie bidirektionaler Iterator Wahlfreier Zugriff: iter[]; Nächstes Element: iter += n; iter -= n; Vergleiche: iter1 < iter2,... C++ Standard Template Library (STL) p.17/41
STL Iteratoren: Beispielimplementierung template <class Container> class back_insert_iterator { protected: Container* container; public: typedef Container typedef void container_type; value_type; explicit back_insert_iterator(container& x) : container(&x) {} }; back_insert_iterator<container>& operator=(const typename Container::value_type& value) { container->push_back(value); return *this; } back_insert_iterator<container>& operator*() { return *this; } back_insert_iterator<container>& operator++(); //... C++ Standard Template Library (STL) p.18/41
STL Funktionen Bestimmte Algorithmen akzeptieren Funktionen als Argumente. Beispiel std::for_each(): void printelement(int value) { std::cout << "The list contains " << value << std::endl; } int main() { std::list<int> alist;... std::for_each(alist.begin(), alist.end(), printelement); } C++ Standard Template Library (STL) p.19/41
STL Function Objects operator()() ist als Member Funktion implementiert Wird ein Function Object benutzt wird der function call operator aufgerufen Beispiel std::find_if(): class biggerthan { public: const int testvalue; biggerthan(int x) : testvalue(x) { } }; bool operator()(int val) const { return val > testvalue; } list<int>::iterator firstbig = find_if(alist.begin(), alist.end(), biggerthan(12)); C++ Standard Template Library (STL) p.20/41
STL Container STL bietet Container-Datenstrukturen an Container können verschiedener Typen halten: fundamentale Typen (int, char,...) Pointer benutzerdefinierte Datentypen Container können keine Referenzen halten Schnittstellen weitestgehend vereinheitlicht Es werden folgende Datenstrukturen angeboten Sequenzen (vector, deque, list, slist, bit vector) Adaptierte Sequenzen (stack, queue, priority queue) Assoziative Container (set, map, multiset, multimap) C++ Standard Template Library (STL) p.21/41
Sequence Container Elemente sind strikt linear angeordnet Unterstützten Einfügen und Löschen von Elementen Typen: Front Insertion Sequence Back Insertion Sequence Front und Back Insertion Sequence C++ Standard Template Library (STL) p.22/41
Assoziative Container Unterstützten effizientes Auffinden von Elementen über Keys Unterstützten Einfügen und Löschen von Elementen Elemente können nicht an einer bestimmten Position eingefügt werden Key ist entweder das Element selbst (set) oder ein ein spezieller Wert des eingefügten Elements Keys dürfen nicht verändert werden Typen: Simple Associative Container Pair Associative Container Sorted Associative Container Unique Associative Container Multiple Associative Container... C++ Standard Template Library (STL) p.23/41
STL Container: vector Sequentieller Container Verallgemeinerung eines gewöhnlichen C Arrays Indizierte Datenstruktur, Zugriff mittels operator[] möglich Unterschiede zu normalen Arrays: Größe des Vektors ändert sich dynamisch Neue Elemente können überall eingefügt werden (effektiv jedoch nur am Ende, im schlimmsten Fall müssen alle Elemente verschoben werden - vergleiche deque) Ein Vektor weiß mehr über sich als ein normales Array: Größe potentielle Größe Wieviele Elemente er aufnehmen kann ohne neuen Speicher allokieren zu müssen Einfügen in einen Vektor ist C++ Standard Template Library (STL) p.24/41
STL Container: vector Operationen Copy Konstruktor muss definiert sein Generische Algorithmen verwenden Operatoren: operator==(), operator<(), operator=() Initialisierung vector<int> vec_one(10,0); Initialisierung durch Zuweisung: vector<int> vec_two(vec_two); Initialisierung durch Elemente aus anderen Containern vector<int> vec(alist.begin(), alist.end()); Zuweisung durch assign() vec.assign(alist.begin(), alist.end()); vec.assign(3, 7);... C++ Standard Template Library (STL) p.25/41
STL Container: vector Typen Type value type const iterator reverse iterator const reverse iterator reference const reference pointer const pointer size type difference type allocator type Definition The type of the elements maintained by the vector. An iterator that does not allow modification of the underlying sequence. An iterator that moves in a backward direction. A combination constant and reverse iterator. A reference to an underlying element. A reference to an underlying element that will not permit the element to be modified. A pointer to an underlying element. A constant pointer to an underlying element. An unsigned integer type, used to refer to the size of containers. A signed integer type, used to describe distances between iterators. The type of allocator used to manage memory for the vector. C++ Standard Template Library (STL) p.26/41
STL Container: vector Member Funktionen 1/2 Indizieren eines Vektors vec[1] = 17; cout << vec[1] << endl; Größenabfragen size() - Anzahl der Elemente capacity() - reservierter Speicher max_size() - maximale Größe empty() - effizienter als size() zu 0 zu vergleichen Größenänderungen vec.reserve(20); vec.resize(12, 0); C++ Standard Template Library (STL) p.27/41
STL Container: vector Member Funktionen 2/2 Einfügen und Löschen von Elementen: Einfügen kann in schlechtesten Fall O(n) Zeit benötigen vec.push_back(21) - sehr effizient, wenn genügend Speicher reserviert ist vec.pop_back() insert: vector<int>::iterator pos = find(v.begin(), v.end(), 7); // then insert the 12 before the 7 v.insert(pos, 12); v.insert(pos, 6, 14); // insert six copies of 14 erase: v.erase(where); v.erase(where, v.end()); C++ Standard Template Library (STL) p.28/41
list: Bidirektionale Iteratoren Doppelt verlinkt Liste ist nicht unbedingt geordnet Weitere Sequenzen Auf Elemente kann nicht über einen Index zugegriffen werden Einfügen und Löschen verursacht konstante Kosten slist: Nur vorwärts Iteratoren Einfach verlinkte Liste Kosten wie list deque (Doppelschlange): Ähnlich wie vector Auf Elemente kann über Index zugegriffen werden operator[] Einfügen am Anfang und am Ende in konstanter Zeit, ansonsten in lineare Zeit C++ Standard Template Library (STL) p.29/41
Verfügen über keine Iteratoren. stack: LIFO Adaptierte Sequenzen Memeber Funktionen: empty(), size(), top(), push(newelement), pop() vector kann auch als Stack verwendet werden queue: FIFO Member Funktionen: empty(), size(),front(),back(), push(newelement), pop() priority queue: Oberstes Element ist immmer das größte Element C++ Standard Template Library (STL) p.30/41
STL Container: set Sammlung von Objekten (jedes Objekt kommt nur einmal vor) set ist immer geordnet (Objekte müssen operator<() implementiert haben) Optimiert für Einfüge- und Löschoperationen und Suchoperationen Instantiierung: std::set<int> set_one; std::set<int, std::greater<int> > set_two; Einfügen nur mit insert: std::set<int> set_one; std::set<int, std::greater<int> > set_two; C++ Standard Template Library (STL) p.31/41
STL Container: Mengenoperationen auf set Subset Test: includes(a.begin(), a.end(), b.begin(), b.end()) set_union() set_intersection() set_difference() set_symmetric_difference() C++ Standard Template Library (STL) p.32/41
Weitere Assoziative Container set map multiset multimap hash set hash map hash multiset hash multimap hash (Funktion) C++ Standard Template Library (STL) p.33/41
Non-mutating algorithms Mutating algorithms Algorithmen for each: Wendet eine Funktion auf alle Elemente an: template <class Arg> class out_times_x : private unary_function<arg,void> { private: Arg multiplier; public: out_times_x(const Arg& x) : multiplier(x) { } void operator()(arg& x) { cout << x * multiplier << " " << endl; } }; for_each(v.begin(), v.end(), f2); C++ Standard Template Library (STL) p.34/41
Non-mutuating: find, find if find: list<int>::iterator result = find(l.begin(), L.end(), 7); find if: struct isleapyear { bool operator()(unsigned int year) const { if (0 == year % 400) return true; if (0 == year % 100) return false; if (0 == year % 4) return true; return false; } }; list<int>::iterator firstleap = find_if(alist.begin(), alist.end(), isleapyear()); C++ Standard Template Library (STL) p.35/41
Non-mutuating: adjacent find, find first of adjacent if: findet nebeneinander liegende Elemente: int A[] = {1, 2, 3, 3, 4, 6, 5, 7, 8}; const int N = sizeof(a) / sizeof(int); const int* p = adjacent_find(a, A + N, greater<int>()); const int* q = adjacent_find(a, A + N); find first of: const char* WS = "\t\n "; const int n_ws = strlen(ws); char* s = "This sentence contains five words."; char* end = find_first_of(s, s + strlen(s), WS, WS + n_ws); WS, WS + n_ws); printf("first word of s: %.*s\n", end - s, s); C++ Standard Template Library (STL) p.36/41
Weiter Non-mutating Algorithmen count count_if mismatch equal search: findet die erste Subsequenzen: search(a.begin(), a.end(), b.begin(), b.end()); search_n: int* result = search_n(first, last, count, val); find_end: findet die letzte Subsequenzen C++ Standard Template Library (STL) p.37/41
copy: Mutating Algorithmen copy(v.begin(), v.end(), ostream_iterator<int>(cout, )); copy n: copy(v.begin(), 3, l.begin()) copy backward: copy_backward(x.begin(), X.begin() + 3, X.end()); 1 2 3 4 5 0 0 0 0 0 0 0 0 0 1 2 3 4 5 0 0 0 0 0 0 1 2 3 swap, iter swap, swap ranges: swap(x, y); swap_ranges(v1.begin(), V1.end(), V2.begin()); transform: transform(v1.begin(), V1.end(), V2.begin(), V3.begin(), plus<int>()); V1: 1 1 1 1 1 1 V2: 2 2 2 2 2 V3: 3 3 3 3 3 C++ Standard Template Library (STL) p.38/41
Weitere: Mutating Algorithmen fill, fill n generate, generate n remove, remove if, remove copy, remove copy if unique, unique copy 1 3 3 3 2 2 1 1 3 2 1 reverse, reverse copy rotate, rotate copy random shuffle, random sample, random sample n C++ Standard Template Library (STL) p.39/41
Sortieren: Weitere Algorithmen sort, stable sort, partial sort, partial sort copy is sorted nth element Binary search (sortierte Container): lower bound, upper bound, equal range, binary search Mergen: merge: zwei sortierte Container zu einem sortierten inplace merge 1 3 5 7 2 4 6 8 1 2 3 4 5 6 7 8 Mengen Operationen: includes, set union, set intersection, set difference, set symmetric difference C++ Standard Template Library (STL) p.40/41
Referenzen http://www.sgi.com/tech/stl/ http://www.roguewave.com/support/docs/ leif/foundation/html/stdlibug/booktoc.html C++ Standard Template Library (STL) p.41/41