Programmieren - Standard Template Library (STL)

Transcrição

Programmieren - Standard Template Library (STL)
FB Informatik
Prof. Dr. R.Nitsch
Programmieren - Standard Template Library (STL)
Reiner Nitsch
 [email protected]
Literatur zu STL
FB Informatik
Prof. Dr. R.Nitsch
Ulrich Breymann
Designing Components with the C++ STL
(2000)
ISBN 0 201 67488 2
Free download of the revised and improved edition as a PDFfile for non-commercial purposes:
http://www.ubreymann.de/stlbe.html
David R. Musser, Gillmer J. Derge, Atul Saini.
STL Tutorial and Reference Guide: C++ Programming with the
Standard Template Library, 2nd Edition (2001)
ISBN: 0201379236
Price: ~50$
07.12.2012
C++ Standard Template Library (STL)
2
Begriffsdefinitionen
FB Informatik
Prof. Dr. R.Nitsch
 Behälterklassen (Container)
 Container sind Objekte, die andere Objekte speichern und verwalten (Einfügen,
Lesen, Löschen, Kopieren, Suchen, Sortieren, …)
 Die Container enthalten i.A. Objekte desselben Typs, wobei die Objekte auch Zeiger
sein können.
 Die STL bietet 2 Container-Kategorien an:
 Sequenzcontainer
 Assoziative Container: Die Daten in diesen Containern werden nicht mittels Index
adressiert sondern über einen Schlüsselwert beliebigenTyps.
Beispiel: Deutsch-Englisches Wörterbuch. Die deutschen Wörter bilden den Schlüsselwert zum
Auffinden der gespeicherten Daten (=englische Wörter):
cout << dict_ge_en["Sprache"] << endl;
Ausgabe: language
Andere Bezeichner für Assoziative Container sind Dictionary (Smalltalk, Python, ObjectiveC, PostScript, C#), einer Map (C++, Java), Hash (Perl, Ruby) oder einer Hashtable/Hashmap
(Java, Windows PowerShell)
 Gemeinsamkeiten dieser Container
Konstruktoren, Destruktor, Methoden für Elementzugriff, Einfüge- und Lösch-Operationen
eigene Speicherverwaltung (wachsen, wenn der reservierte Speicher nicht mehr ausreicht)
07.12.2012
C++ Standard Template Library (STL)
3
Grundsätzliches zu Containern
FB Informatik
Prof. Dr. R.Nitsch
 Sequentielles Aufsuchen der Elemente eines Containers
 „Sequentiell“ impliziert, dass eine Reihenfolge definiert und dem Anwender bekannt sein
muss.
 Um die interne Datenstruktur zu verbergen, werden i.A. „Iteratoren“ als Mittel zur
Kontrollabstraktion eingesetzt.
 STL-Iteratoren
 Sind Objekte, die wie Pointer anzuwenden sind
 bieten lesenden und schreibenden Zugriff auf den Containerinhalt
 Können von einem zu einem anderen Containerelement bewegt werden, wobei die Details der
Bewegung verborgen bleiben (Kontrollabstraktion)
 Erlauben die Formulierung von Algorithmen, die Containerinhalte verarbeiten, unabhängig
von der jeweiligen Datenrepräsentation (generische Algorithmen)
07.12.2012
C++ Standard Template Library (STL)
4
Grundsätzliches zu Containern
FB Informatik
Prof. Dr. R.Nitsch
Was soll ein Container enthalten?
 Bei der Wertsemantik legt der Container von allen zum Einfügen übergebenen
Nutzdaten jeweils eine Kopie an, und speichert die Kopie. Eine danach erfolgte
Änderung der Orginale durch den Aufrufer wirkt sich nicht auf die Kopien im
Container aus.
 Bei der Referenzsemantik werden effektiv nur Referenzen auf die einzufügenden
Objekte gespeichert. Eine Änderung der Orginale durch den Aufrufer wirkt sich
auch nach dem Einfügen noch auf den Inhalt des Containers aus.
 Alle STL-Container arbeiten mit Wert-Semantik. Aber auch Referenzsemantik lässt
sich darstellen, indem den Containern lediglich Pointer mit den Adressen der Daten
übergeben werden.
07.12.2012
C++ Standard Template Library (STL)
5
Grundsätzliches zu Containern
FB Informatik
Prof. Dr. R.Nitsch
 Wachstum von Behältern
 Jedes Wachsen bedeutet Anfordern (Allokieren) eines größeren Speicherbereichs,
Umkopieren und Löschen des bisherigen Speicherbereichs (Zeitaufwändig)
 Zugriff auf Container-Elemente
 Soll ein Container beim Lesen seiner Elemente vom Typ T Referenzen (T&) zurückgeben?
Kein Kopieraufwand .
Missbrauch möglich: Ändern des Werts eines Elements in einem sortierten Container über die
Referenz .
Bei dynamisch wachsenden Containern können Referenzen und Iteratoren ungültig werden, wenn die
Elemente automatisch in einen größeren zusammenhängenden Speicherbereich umkopiert werden .
 Container, die Referenzen/Zeiger zurück geben, sollten ihre Elemente im
Hauptspeicher möglichst nicht verschieben müssen, also auch nicht
wachsen müssen.
07.12.2012
C++ Standard Template Library (STL)
6
Standard Template Library (STL) Components Overview
FB Informatik
Prof. Dr. R.Nitsch
 Die C++ STL enthält mehrere typparametrisierte
Container Klassen
, Header <vector>
, Header <deque>
, Header <list>
, Header <set>
, Header <map>
07.12.2012
C++ Standard Template Library (STL)
Algorithm
OutputIterator
 Diese Container verwenden die Wert-Semantik, d.h. sie
kopieren intern die einzufügenden Elemente anstatt nur
eine Referenz darauf abzuspeichern.
 Die C++ STL enthält mehrere typparametrisierte
Algorithmen (ca. 70 verschiedene ) im Header
<algorithm>, die hinsichtlich Laufzeiteffizienz optimiert
sind.
 Die STL definiert mehrere Funktionsobjekte im Header
<functional>, um verschiedene Algorithmen an
unterschiedliche Aufgabenstellungen anzupassen.
Container
(list)
Container
(vector)
InputIterator
vector<T>
deque<T>
list<T>
set<T>
map<Key,T>
…
InputIterator






Container
(map)
7
Container - Übersicht
FB Informatik
Prof. Dr. R.Nitsch
Container
unordered_multiset
unordered_set
Sequenz-Container
array
vector
deque
stack
queue
priority queue
set
map
■1 ●1
▲1
Menge von
Unikaten
neu:
unordered_map
Assoziative Container
Sequenz-Adapter
list
unordered_multimap
multiset
■4 ●6
▲13
forward_list
auch Duplikate
■1 ●1
Keys ▲1
multimap
☺☼
3■ ●
3▲ 2
 
(einfach verkettet)
☺ Data
☼
◊

☼
♂
◊
Siehe auch: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang98/html/LIB_CONT.asp
07.12.2012
C++ Standard Template Library (STL)
8
Alle STL-Container: Anforderungen an die Objekte
 Die Objekte (Elemente) eines Containers müssen
kopierbar (copy-constructable) sein und die erzeugte
Kopie muss den gleichen 'Wert' wie das Original besitzen.
Dieses Fähigkeit erhalten Objekte durch den KopierKonstruktor.
 Die Objekte müssen zuweisbar (assignable) sein. Hierzu
muss die Klasse den Zuweisungsoperator definieren, wenn
die Standard-Variante nicht ausreicht.
 Die Objekte müssen zerstörbar (destructable) sein.
Container entfernen ihre Elemente durch den impliziten
Aufruf des Element-Destruktors.
Aber: Wenn der Container Pointer speichert, wird auch
nur der von diesen belegte Speicherplatz freigegeben.
Die Destruktoren der referenzierten Objekte muss also
das Kompositum aufrufen, dessen Komponente der
Container.
 Alle diese Operationen werden implizit durch den
Compiler für jede Klasse generiert. Man muss diese
Operationen also nur für nicht-triviale Klassen (solche,
die z.B. dynamische Daten oder andere Objekte
enthalten) selbst implementieren.
07.12.2012
FB Informatik
Prof. Dr. R.Nitsch
class Any {
... // Private Daten
public:
// Kopierkonstruktor
Any(const Any& src);
...
};
class Any {
... // Private Daten
public:
// Überladener = Operator
Any & operator=(const Any &rhs);
...
};
class Any {
... // Private Daten
public:
// Destruktor
~ Any();
...
};
C++ Standard Template Library (STL)
9
Alle STL-Container: Anforderungen an die Objekte
 Einige Algorithmen funktionieren nur,
wenn die Objekte den operator==
implementieren. Beispiel: std::find.
 Algorithmen und Container mit Sortierfunktionen setzen den operator< voraus.
 Weitergehende Anforderungen bezüglich
Vergleichsoperatoren werden STL-intern
durch eine Kombination der Operatoren
„==„ und „<„ erfüllt.
Beispiele:
x>=y das Gleiche wie !(x<y)
und
x>y
das Gleiche wie y<x
und
x!=y das Gleiche wie !(x==y)
07.12.2012
FB Informatik
Prof. Dr. R.Nitsch
class Any
{
... // Private Daten
public:
// Implementierung == Operator
bool operator==(const Any& rhs) const;
...
};
class Any
{
... // Private Daten
public:
// Implementierung < Operator
bool operator<(const Any& rhs) const;
...
};
C++ Standard Template Library (STL)
10
Musterklasse Any (wird in Beispielen verwendet)
FB Informatik
Prof. Dr. R.Nitsch
class Any {
int* pa;
public:
Any( int i=0 ) { pa = new int(i); }
Any( const Any& a ) { pa = new int(*a.pa); }
~Any() { delete pa; }
int get() const { return *pa; }
Any& operator= ( const Any& a ) {
this->pa = a->pa;
return *this;
}
bool operator== ( const Any& a ) const { return this->pa == a->pa); }
bool operator< ( const Any& a ) const { return this->pa < a->pa; }
};
ostream& operator<< ( ostream& os , const Any& a )
{
os << a.get();
return os;
}
07.12.2012
C++ Standard Template Library (STL)
11
Alle STL Container bieten Iteratoren
Container-Klasse: X
(z.B. list<int> für X)
X::iterator
X::reverse_iterator
first
Container-Elemente
begin()
rend()
FB Informatik
Prof. Dr. R.Nitsch
--iter
++riter
last
iter
++iter
riter
--riter
end()
rbegin()
 Alle STL-Container stellen Iteratoren zur Verfügung, die sich bezüglich einer
Inkrementierung unterschiedlich verhalten:
 X::iterator:
Normaler Iterator, mit dem beim Inkrementieren ein Container
von vorne nach hinten traversiert werden kann.
 X::reverse_iterator: Ein Iterator, mit dem durch Inkrementieren ein Container von
hinten nach vorne traversiert werden kann; in STL implementiert als
Adapterklasse der normalen Iteratoren
07.12.2012
C++ Standard Template Library (STL)
12
Read-only Iterator Typen
FB Informatik
Prof. Dr. R.Nitsch
 Iteratoren können vom Typ read-write-access und read-only-access sein.
 Der read-write Iterator-Typ iterator liefert bei der Dereferenzierung eine
Referenz auf das Element-Objekt (T&), die auch schreibenden Zugriff erlaubt.
 Der read-only Iterator-Typ const_iterator liefert bei der Dereferenzierung
lediglich eine const-Referenz (const T&) ohne Schreibzugriff auf das Objekt
vector<Konto> kto;
vector<Konto>::iterator iter = kto.begin();
iter->stand = iter->stand + 100; // "stand" muss hier public sein. Container darf nicht leer sein!
vector<Konto>::const_iterator const_iter = kto.begin();
double betrag = const_iter->stand; OK, weil nur lesender Zugriff
Fehler, weil schreibender Zugriff über const_iterator
const_iter->stand = 100;
OK! const bedeutet nicht, daß der Iterator selbst nicht verändert
const_iter++;
werden darf, sondern nur das Element auf das er zeigt!
Achtung: keine Bereichs-Kontrolle für Iteratoren
 Alle STL-Container definieren sowohl die
read-write-access als auch die
read-only-access Iteratorvariante.
Hinweis: MS Visual C++2005ff weicht hier
vom Standard ab und bietet sogenannte
"Checked Iterators": Programmabbruch zur
Laufzeit, wenn Iterator nicht im zulässigen
More on this:Visual C++ 8.0 Hijacks the C++ Standard Bereich.
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=259 Gleiches gilt auch für den []-Operator.
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=260
07.12.2012
C++ Standard Template Library (STL)
13
Alle STL Container: Gemeinsame Typ-Definitionen
Typ-Definitionen
X::value_type
X::reference
X::const_reference
X::pointer
X::const_pointer
X::iterator
X::const_iterator
Legende
Typ der Werte im Container (i.A: T bei
Sequenzcontainer, Key bei std::set und
pair<Key,T> bei std::map)
entspricht X::value_type&
entspricht const X::value_type&
entspricht X::value_type*
entspricht const X::value_type*
Kontrollabstraktion zum traversieren des
Containers in Vorwärtsrichtung
wie X::iterator aber nur lesender Zugriff auf
ElementWerte
X::reverse_iterator
X::const_reverse_iterator wieX::iterator aber Rückwärtsrichtung
X::difference_type
kann Abstand zweier Iteratoren darstellen
X::size_type
kann Größe eines Containers darstellen.
• Die Container stellen mittels typedef-Anweisungen mehrere
Datentypen zur Verfügung.
• Durch Verwendung dieser Typ-Bezeichner in Anwendungen bzw.
Algorithmen werden diese vom tatsächlichen, aktuellen Datentyp
der Container weitgehend unabhängig.
• Werden zu einem späteren Zeitpunkt, anstelle von Any-Objekten,
Objekte vom Typ Konto im Container abgelegt, so ändert sich
damit auch der Datentyp der Variablen A1::value_type ist dann ein
Alias für den Datentyp Konto.
Konstruktoren
X()
X(a); X b(a);
a.~X()
07.12.2012
FB Informatik
Prof. Dr. R.Nitsch
Standard-Konstruktor; erzeugt leeren Container
Copy-Konstruktor
Destruktor
X
ist eine Container-Klasse für Objekte vom Typ T
a,b sind Variablen/Objekte vom Typ X
r
ist eine Referenz-Variable/-Objekt vom Typ X&
// Typ des Vektors
typedef vector<Any> AnyVect;
// Vektor definieren
AnyVect v;
… // v füllen
// Variable definieren deren Datentyp mit dem
// Datentyp der Vektor-Elemente überein stimmt
Any A1 = v[0];
vector<Any>::value_type A1= v[0];
AnyVect::value_type A1= v[0];
Äquivalente Anweisungen!
// Erzeugt einen leeren Container
list<Any> anyList;
// Dupliziert einen Container
list<Any> myList(anyList)
C++ Standard Template Library (STL)
14
Alle STL Container: Gemeinsame Methoden
iterator X::begin() Gibt Iterator auf das erste Containerelement
iterator X::end() Gibt Iterator, der die Ende-Markierung des
Containers kennt.
reverse_iterator
X::rbegin()
Gibt reverse-Iterator zurück, der das Anfangselement für umgekehrtes Traversieren kennt.
reverse_iterator
X::rend()
Gibt reverse-Iterator, der die Ende-Markierung
für reverses Traversieren kennt.
size_type size()
gibt aktuelle Anzahl Elemente im Container
bool empty()
liefert true, wenn Container leer ist
a==b, a!=b
true bei elementweiser (Un)Gleichheit;
benutzt X::value_type::operator==
a<b
vergleicht 2 Container lexikografisch;
benutzt X::value_type::operator<
a>b
returns true, wenn b<a
a<=b
returns true wenn !(b<a)
a>=b
returns true, wenn !(a<b)
r=a
Zuweisungsoperator für Container
a.swap(b)
Vertauschen der Inhalte 2er Container
gleichen Typs (konstante Komplexität O(1)!).
FB Informatik
Prof. Dr. R.Nitsch
// Any-Vektor definieren
AnyVect v;
// hier Any-Vektor füllen…
AnyVect::iterator iter;
// Kompl. Container ausgeben
for ( iter = v.begin();
iter != v.end(); ++iter )
cout << *iter << endl;
// Any-Vektor definieren
AnyVect v;
// hier Any-Vektor füllen …
// Anzahl der Elemente ausgeben
cout << v.size() << endl;
// Test ob Vektor Elemente enthält
if( v.empty() )
cout << "Keine Elemente im Vektor!\n";
// Any-Vektor definieren
AnyVect anyV1, anyV2;
...
// Any-Vektor definieren
// Container-Inhalte vergleichen
AnyVect anyV1, anyV2;
if( anyV1 == anyV2 )
// Container füllen
cout << "Container enthalten die"
// Container-Inhalte vertauschen (konstante Komplexität)
" gleichen Elemente!\n";
anyV1.swap( anyV2 );
// Vergleich auf kleiner als
// Container zuweisen
if( anyV1 < anyV2 )
anyV2
=
anyV1;
15
07.12.2012
C++ Standard Template Library
cout (STL)
<< "anyV1 ist kleiner anyV2 \n";
STL Sequenzcontainer
FB Informatik
Prof. Dr. R.Nitsch
bietet wahlfreien Zugriff auf Objektsequenzen ( O(1) ) variabler
Länge mit schellem Einfügen und Löschen am Ende der Sequenz
wie vector, aber schnelles Einfügen und Löschen am Anfang und
Ende der Sequenz
kein wahlfreier sondern linearer Zugriff ( O(N) ) auf eine Sequenz
variabler Länge (hier N) aber schnelle Einfüge- und Löschoperationen
an beliebiger Stelle ( O(1) )
 vector<T>
 deque<T>
 list<T>
Einfügen / Löschen
Container
ElementZugriff
Beginn
Mitte
Ende
vector<T>
O(1)
O(N)
O(N)
O(1)
deque<T>
O(1)
O(1)
O(N)
O(1)
list<T>
O(N)
O(1)
O(1)
O(1)
T a[N]
O(1)
O(N)
O(N)
O(1)
07.12.2012
Iterator Typ-Definitionen
Iterator-Kategorie
vector<T>::iterator
mutable random access
vector<T>::const_iterator
constant random access
deque<T>::iterator
mutable random access
deque<T>::const_iterator
constant random access
list<T>::iterator
mutable bidirectional
list<T>::const_iterator
constant bidirectional
T*
mutable random access
const T*
constant random access
C++ Standard Template Library (STL)
16
Alle Sequenz-Container: Zusätzliche Konstruktoren
FB Informatik
Prof. Dr. R.Nitsch
Konstruktoren:
Legende
Standard-Konstruktor
Initialisiert Container mit n Kopien vom Typ T
Für Typ T muss der Standard-Konstruktor definiert
sein!
X(n,t); X a(n,t) Erzeugen eine Sequenz mit n Kopien von t.
X(i,j); X a(i,j) Erzeugen eine Sequenz mit gleichem Inhalt wie der
Range [i,j)
X ist eine Container-Klasse für Objekte vom Typ T
a ist eine Variable vom Typ X
i,j Input-Iteratoren und [i,j) ist ein gültiger Bereich
n Variable vom Typ X::size_type
p gültiger Iterator für a
q, q1, q2 gültige dereferenzierbare Iteratoren für a
und [q1,q2) ist ein gültiger Bereich
t Variable vom Typ X::value_type
X(); X a;
X(n); X a(n);
• Jeder Sequenz-Container kann auf
die fünf rechts dargestellten
Arten definiert werden.
• Diese Definitionen gelten generell
auch für die Container deque und
list.
07.12.2012
#include <vector>
using std::vector;
class Any { /*…*/ };
// Leeren Vektor definieren
vector<Any> vect1;
// Vektor mit 5 Elementen definieren
vector<Any> vect2(5);
// Vektor aus 5 Objekten mit Wert Any(10) erzeugen
vector<Any> vect3(5, Any(10));
// Any-Feld definieren/initialisieren
Any array[4] = { Any(1),Any(2),Any(3),Any(4) }
// Vektor mit Feldinhalt initialisieren
vector<Any> vect4( &array[0], &array[4] );
vector<Any> vect5( vect3.begin(), vect3.end() );
C++ Standard Template Library (STL)
17
Alle Sequenz-Container: Zusätzliche Methoden
FB Informatik
Prof. Dr. R.Nitsch
// Vektor definieren
typedef vector<Any> AnyVect;
Fügt eine Kopie von t vor p ein.
AnyVect v, v1;
Gibt Iterator auf eingefügten Wert zurück
// Den Wert Any(i) einf.
void X::insert(p,n,t)
Fügt n Kopien von t vor p ein.
iter = v.end();
void X::insert(p,i,j)
Fügt Kopien der Elemente im Range [i,j)
for( int i=4; i>0; --i )
eines anderen Containers vor p ein.
iter = v.insert( iter, Any(i) );
1234
void X::push_back(t)
Fügt eine Kopie von t am Ende ein
//
Den
Wert
Any()
vor
der
1.
Position
einf.
void X::assign(i,j)
Entspricht { clear(); insert( begin(), i, j); }
01234
v.insert( v.begin(), Any() );
void X::assign(n,t)
Entspricht { clear(); insert( begin(), n, t ); }
// 2x den Wert Any(5) vor der 6. Position einf.
v.insert( v.begin()+5, 2, Any(5) );
Elementzugriff:
// Feld definieren
reference X::front()
Gibt Referenz auf 1.Element
Any array[] = { Any(6), Any(7), Any(8) };
reference X::back()
Gibt Referenz auf letztes Element
// Any-Feld am Ende einfuegen
Beide Rückgaben sind undefiniert, wenn
v.insert(v.end(),&array[0],&array[3]);
der Container leer ist!
// Existierenden Vektor löschen und aus aus array neu befüllen
Löschoperationen:
v1.assign( array, &array[3] );
678
iterator X::erase(q)
Löscht das Element, auf das q verweist.
//
Erstes
Element
auslesen
Der Ergebnis-Iterator verweist auf das
AnyVect::value_type var = v.front();
Element hinter q oder a.end(), wenn das
//
Letztes Element auslesen
letzte Element gelöscht wurde.
cout << var << ' ' << v.back();
08
iterator X::erase(q1,q2) Löscht alle Elemente im Bereich [q1,q2).
// 2. Element entfernen
v: 0 1 2 3 4 5 5 6 7 8
Der Ergebnis-Iterator verweist auf das
cout << *v.erase(v.begin()+1);
2
Element hinter q2 oder a.end(), wenn das
// Letzte 4 Elemente entfernen v: 0 2 3 4 5 5 6 7 8
letzte Element gelöscht wurde.
v.erase( v.end()-4, v.end() );
void X::pop_back()
Löscht letztes Element
// Letztes Element entfernen
v: 0 2 3 4 5
void X::clear()
Löscht alle Elemente im Container
v.pop_back();
v: 0 2 3 4
void X::resize(n,t)
Löscht alle Elemente am Ende oder füllt
//Containergröße verändern
am Ende mit Kopien der Objekte t auf bis
v: 0 2 3 4 7 7
v.resize( 6, Any(7) );
size() == n. Eine Reduzierung des
// Alle Elemente entfernen
allokierten Speichers wird dadurch nicht
v.clear();
erzwungen.
18
07.12.2012
C++ Standard Template Library (STL)
Einfügeoperationen:
iterator X::insert(p,t)
Container vector und deque : Direkter Elementzugriff
Elementzugriff:
… = a[n]
lesender Direktzugriff ohne Indexüberprüfung
a[n]= …
schreibender Direktzugriff ohne Indexüberprüfung
… = a.at(n)
lesender Direktzugriff mit Indexüberprüfung
a.at(n)= …
schreibender Direktzugriff mit Indexüberprüfung;
throw( std::out_of_range )
 Der Zugriff auf die einzelnen Elemente eines
Vektor/Deque-Containers kann, wie bei Feldern
üblich, mit dem Indexoperator [] erfolgen. Es
findet keine Indexüberprüfung statt.
 Über die Memberfunktion at(..) kann
lesend/schreibend mit Indexprüfung
( 0<= index <=size() ) auf die Elemente
zugegriffen werden. Bei Indexfehlern wird eine
out_of_range Exception ausgeworfen.
 Bei list Objekten ist der []-operator nicht
implementiert, da der Zugriffsaufwand mit O(N) zu
ineffizient ist.
07.12.2012
FB Informatik
Prof. Dr. R.Nitsch
// Indizierter Elementzugriff
Any var = v[3]; // lesend
v[4] = var;
// schreibend
// Abgesicherter Elementzugriff
// kann out_of_range Exception auslösen
var = v.at(15); // Fehler
v.at(0) = var;
Hinweis: MS Visual C++ 2005 weicht hier
vom Standard ab und bietet sogenannte
"Checked Iterators": Programmabbruch zur
Laufzeit, wenn Iterator nicht im zulässigen
Bereich. Gleiches gilt auch für den []Operator.
Mehr dazu hier:
http://msdn2.microsoft.com/enus/library/aa985965(VS.80).aspx
C++ Standard Template Library (STL)
19
Container deque und list : Zusätzliche Methoden zum Einfügen von Elementen
FB Informatik
Prof. Dr. R.Nitsch
Einfügen und Löschen von Elementen:
void X::push_front(t) Fügt Objekt t am Listenanfang ein
void X::pop_front() Entfernt erstes Objekt im Container
 Elemente können zusätzlich über die
Memberfunktion void push_front(t) am
Beginn von list- und deque-Containern
eingefügt werden.
 Das erste Element von list- und dequeContainern kann zusätzlich über die
Memberfunktion void pop_front()
entfernt werden.
 Beide Methoden sind beim vectorContainer nicht definiert, weil Einfüge- und
Löschoperationen am Beginn dieses
Containers sehr ineffizient sind (O(N))!
07.12.2012
// Vektor definieren
list<Any> myList;
//Objekt Any(1) am Anfang einfügen
myList.push_front( Any(1) );
// Erstes Listenelement entfernen
myList.pop_front();
C++ Standard Template Library (STL)
20
Zusätzliche Methoden für list-Container
FB Informatik
Prof. Dr. R.Nitsch
Return type method Meaning
void merge(list&)
Merges two sorted lists, using T::operator<(const T&) (time complexity O(n)).
void merge(list&,Compare_object)
Merges two sorted lists, using a Compare_object for the comparison of elements (O(n)).
void push_front(const T& t)
Inserts an element at the beginning.
void pop_front()
Deletes the first element.
void remove(const T& t)
Removes all elements that are equal to the passed element t (O(n)).
void remove_if(Predicate pred)
Removes all elements to which the predicate applies (O(n)).
void reverse()
Reverses the order of elements in the list (O(n)).
void sort()
Sorts the elements in the list. Time complexity is O(~N log N). The sorting criterion is the
T::operator<(const T&) defined for the elements. Remark: Stable
void sort(Compare_object)
as sort(), but with the sorting criterion of the comparison function object.
void splice(iterator p,list&x, iterator i) Inserts element *i of x before p and removes *i from x.
void splice(iterator pos, list& x,
iterator first, iterator last)
Inserts elements in the range [first, last) of x before pos and removes them from x. Calling the
same object (that is, &x == this), takes constant time, otherwise, the cost is of the order O(n). pos
must not lie in the range [first, last).
void splice(iterator pos, list& x)
Inserts the contents of list x before pos. Afterwards, x is empty.
void unique()
Deletes identical consecutive elements except for the first one (cost O(n)). Application to a sorted
list leads to the effect that no element occurs more than once.
void unique(binaryPredicate)
Ditto, only that instead of the identity criterion another binary predicate is used.
07.12.2012
C++ Standard Template Library (STL)
21
Container vector : Größenmanagement
 Memberfunktion vector::capacity()
ermittelt Maximalgröße, bis zu der der VektorContainer erweitert werden kann, ohne dass
hierfür neuer Speicherplatz angefordert
werden muss.
 Memberfunktion vector::reserve(n) legt
die Größe des allokierten Speicherplatzes fest.
Ein Größenreduzierung kann mit reserve(n)
nicht erzwungen werden.
 Sie sind deshalb so interessant, weil nach einer
Anforderung von neuem Speicherplatz für
einen Vektor-Container alle ElementReferenzen und -Zeiger sowie Iteratoren
ungültig werden.
 Für die Container list und deque sind
capacity() und reserve() nicht definiert.
07.12.2012
FB Informatik
Prof. Dr. R.Nitsch
// Feld definieren/initialisieren
int array[] = {1,2,3,4,5};
// Vektor mit Feldinhalt initialisieren
vector<Any> v3(&array[0],&array[5]);
// Kenndaten des Vektors ausgeben
cout << v3.size() << ','
<< v3.capacity() << endl;
5, 5
// Vektor vergroessern
v3.reserve(20);
// Erneut Kenndaten ausgeben
cout << v3.size() << ','
5, 20
<< v3.capacity() << endl;
C++ Standard Template Library (STL)
22
Sortierte Assoziative Container der STL
FB Informatik
Prof. Dr. R.Nitsch
 Elementzugriff O(log2N)
 Speichern die Daten intern in einer Baumstruktur
 Das mathematische Konzept einer Relation oder eine diskrete Abbildung wird mit
map realisiert, das einer Menge mit set
 multimap und multiset erlauben mehrfache identische Schlüssel
Erklärung siehe
STL-Algorithmen
Container
set<T>
Zugriff
O(log N)
Einfügen / Löschen
Beginn Mitte Ende
O(1)
O(1)
O(1)
multiset<T>
O(log N)
O(1)
O(1)
O(1)
map<Key,T>
O(log N)
O(1)
O(1)
O(1)
multimap<Key,T>
O(log N)
O(1)
O(1)
O(1)
Iterator
Iterator-Kategorie
set<T>::iterator
constant bidirectional1)
set<T>::const_iterator
constant bidirectional
multiset<T>::iterator
constant bidirectional1)
multiset<T>::const_iterator
constant bidirectional
map<key,T>::iterator
mutable bidirectional
map<key,T>::const_iterator
constant bidirectional
multimap<Key,T>::const_iterator
mutable bidirectional
multimap<Key,T>::const_iterator
constant bidirectional
1) Microsoft Visual C++ weicht hier vom Standard ab und realisiert "mutable bidirectional" Iteratoren 
07.12.2012
C++ Standard Template Library (STL)
25
Assoziativer Container map
FB Informatik
Prof. Dr. R.Nitsch
 map speichert Elemente, die aus einem Schlüsselwert "key" und
key_type mapped_type
assoziierten Daten "mapped" bestehen.
 Die Schlüsselwerte sind eindeutig, d.h. es gibt keine 2 Datensätze
MatrikelNr Sudent
mit gleichem Schlüsselwert (keine Duplikate).
 Der Zugriff auf die assoziierten Daten erfolgt über den Schlüsselwert,
TelNr
Name
anstatt über ihre absolute (Index) oder relative (front, back)
Position im Container.
Location
Node
 Eine sortierte Anordnung der Schlüsselwerte ist für den Zugriff nicht
Beispiele assoziierter
erforderlich, reduziert aber den Zugriff auf die Komplexität O(logN)
Daten im map-Element
 Schlüsselwerte und assoziierte Daten werden vom map-Container
gemeinsam in Objekten vom Typ std::pair<const Key, T> aufbewahrt.
 Die Konstanz des Schlüssels gewährleistet, dass er nach dem Einfügen nicht mehr
verändert werden kann. Dies würde die Sortierung zerstören.
 Deklaration der Klasse in der STL
template< class Key,
// Typ von key
class T,
// Typ von mapped
class Compare = std::less<Key> > // Typ des Sortierers
class map { /*…*/ };
// (Key::operator< ist voreingestellt)
Anwendungsbeispiele folgen
07.12.2012
C++ Standard Template Library (STL)
26
1. Beispiel - Wörterbuch
Map_Demo_Anwendung
void main(void) {
map<string,string> dictionary;
FB Informatik
Prof. Dr. R.Nitsch
// Leeres Wörterbuch erzeugen
dictionary.insert(pair<string,string>("Baum","tree"));
// Element aufnehmen
dictionary.insert(pair<string,string>("Auto","car"));
// noch ein Element
cout << dictionary["Baum"] << endl;
// Assoziativer Zugriff
map<string,string>::iterator iter = dictionary.begin();
for( ; iter!=dictionary.end(); ++iter )
cout << (*iter).first << ' ' << iter->second << endl;
// Sortierte Ausgabe
}
tree
Auto car
Baum tree
 Voreingestellt ist, dass der Operator < die interne Reihenfolge der Elemente in
map- bzw- set-Containern bestimmt.
 Falls das unerwünscht ist, muss ein anderes geeignetes Kriterium angeboten
werden: class Compare {
Beispiel:
public: bool operator()(const string& s1, const string& s2) const
{ return s2<s1; }
};
07.12.2012
void main(void) {
Comp compare;
map<string,string,Compare> dictionary(compare);
// weiter wie oben
C++ Standard Template Library (STL)
}
// Sortierte Ausgabe
Buch book
Auto car
27
Container map und multimap : Übersicht und Typdefinitionen
FB Informatik
Prof. Dr. R.Nitsch
Typdefinitionen
 map definiert folgende öffentlichen Datentypen
key_type
mapped_type
Typ Key der Schlüsselwerte
Typ T der zugeordneten Werte
value_type
pointer
reference
X::key_compare
Typ der gespeicherten Werte, pair<const Key,T>
entspricht pair<const Key,T>*
entspricht pair<const Key,T>&
Typ des Funktionsobjekts Compare, das die
Sortierreihenfolge der Schlüssel festlegt
Weitere Typen wie Sequenz-Container
…
Fortsetzung des Beispiels:
map-Element
Key
T
value_type
Typ pair<Key,T>
key_type
mapped_type
typedef dient hier der Abkürzung
void main(void) {
Achtung: Ist die Suche nach dem Schlüssel
// wie bisher
erfolglos, wird ein neues map-Element für
cout << dictionary.size();
2
diesen Schlüssel angelegt. Die assoziierten
typedef map<string,string,Compare> Map
Daten werden mit dem Standardkonstruktor
Map::key_type key = "Ei";
// Typ ist string
T() erzeugt (hier: string() ).
cout << dictionary[key];
3
cout << dictionary.size();
// Schreibender Zugriff auf assoziierte Daten
dictionary[key] = "egg";
// Typ ist string Weitere Informationen zum Einfügen, Suchen und
Map::mapped_type translation;
translation = dictionary[key];
Löschen von Daten finden Sie hier:
egg
cout << word;
Breymann: C++. S. 756ff
}
http://www.cplusplus.com/reference/stl/map/
07.12.2012
C++ Standard Template Library (STL)
28
1. Beispiel - Duplikate
FB Informatik
Prof. Dr. R.Nitsch
void main(void) {
// wie bisher (siehe vorherige Seite)
3
cout << dictionary.size();
dictionary.insert(pair<string,string>("Auto","vehicle")); // Versuch Duplikat einzufügen:
// Schlüsselwert "Auto" gibt es schon
cout << dictionary.size();
3
// Duplikat wurde nicht gespeichert!
Wie kann man dieses Verhalten zuverlässig kontrollieren?
Deklaration von map::insert:
pair<iterator,bool> insert( const value_type& x );
map::insert liefert einen return-value vom Typ std::pair.
1. Member pair::first: Iterator, der auf das neu eingefügte Element oder das Duplikat zeigt
2. Member pair::second: Ist false, wenn der Schlüsselwert bereits enthalten ist, sonst true.
typedef Map::iterator Iterator;
std::pair<Iterator,bool> result;
// 2. Versuch
result = dictionary.insert(Map::value_type("Auto","vehicle"));
cout << result.second << endl;
false // Duplikat wurde nicht gespeichert!
cout << *(result.first) << endl;
Auto car
}
07.12.2012
C++ Standard Template Library (STL)
29
2. Beispiel: Ein Telefonbuch mit class map
FB Informatik
Prof. Dr. R.Nitsch
typedef map<string,long> PhoneMap;
string ist der key_type und long ist der mapped_type
typedef PhoneMap::value_type MapElement;
MapElement entspricht jetzt pair<string,long>
typedef dient hier wieder der Abkürzung
void main() {
// Einfügen mit operator[ ] und insert:
PhoneMap directory;
directory.insert(MapElement("IRedViel",732457));
directory["HauMich"] = 163248;
directory[„DuBiDumm"] = 843756;
directory.insert(MapElement("IRedViel",732458)); // 2. Telefon; wird nicht ausgeführt, weil Schlüssel
// schon existiert
// immer noch kein 2. Telefon. Überschreibt 1. Nummer
directory["IRedViel"] = 732458;
const_iter weil read-only Zugriff ausreicht
PhoneMap::const_iter iter = directory.begin();
for( ; iter!=directory.end(); ++iter)
// Sortierte Ausgabe:
cout << (*iter).first << ' '
DuBiDumm 843756 HauMich 163248 IRedViel 732458
<< iter->second << ' ';
// Suchen im Telefonbuch …
string name = "Bin Laden";
// Suchen mit operator[ ]:
// O( logN )
long number = directory[name];
// number = 0; Achtung: Suchfehler gibt es hier nicht!! Für "BinLaden"
// existiert jetzt ein Eintrag.
iter = directory.find(name);
// Suchen mit Iterator und find
// O( logN )
if( iter!=directory.end() )
// Prüfen, ob Iterator dereferenzierbar ist
cout << (*iter).second;
// O( 1 )
iterator find(k) liefert Iterator
else
auf gefundenen Eintrag oder "past-thecout << name << " hat kein Telefon!" << endl;
end" Iterator wenn nicht gefunden
directory.erase(iter); // Leereintrag "BinLaden" wieder löschen
}
void erase(iter) löscht einzelnes Element an Position iter
07.12.2012
C++ Standard Template Library (STL)
30
Sortierter Assoziativer Container multimap
FB Informatik
Prof. Dr. R.Nitsch
 Unterschiede zu map
 Elemente mit identischem Schlüssel (Duplikate) dürfen mehrfach vorkommen. Die
assoziierten Daten dürfen sich dabei durchaus unterscheiden
Beispiel: mehrere Telefonnummern unter gleichem Namen
 Es gibt keinen Indexoperator T& operator[ ](const key_type& k)
07.12.2012
C++ Standard Template Library (STL)
31
Sortierter Assoziativer Container set
FB Informatik
Prof. Dr. R.Nitsch
 entspricht der Klasse map, mit dem Unterschied, dass nur Schlüsselwerte
gespeichert werden (Elemente = Schlüsselwerte)
 set speichert wie map keine Duplikate
 set hat keinen Indexoperator -> Einfügen nur mit insert(key)
void main(void) {
set<string> names;
// Einfügen mit insert
names.insert("IchSchonWieder");
names.insert(„IbinSchlau");
names.insert(„DuBiDumm");
set<string>::iterator iter = names.begin(); // Sortierte Ausgabe
for( ; iter!=names.end(); ++iter )
DuBiDumm IbinSchlau IchSchonWieder
cout << *iter << endl;
names.insert("IchSchonWieder");
// Duplikat nicht eingefügt. Wie erkennt man erfolgreiches Einfügen?
pair<SetIter,bool> success;
pair<iterator,bool> insert(key)
success = names.insert("IchSchonWieder");
if(success.second==true)
cout << *(success.first) << " eingefuegt";
Duplikat
else cout << "Duplikat";
}
07.12.2012
C++ Standard Template Library (STL)
32
Container set : Übersicht und Typdefinitionen
FB Informatik
Prof. Dr. R.Nitsch
• Deklaration der Klasse in der STL
template< class Key
class Compare = std::less<Key> >
class set { /*…*/ };
// Typ der Schlüssel
// Typ des Sortierers
// (Key::operator< ist voreingestellt)
Definition eines leerenset-Containers: set<Konto> myset;
Typdefinitionen
• set definiert folgende öffentlichen Datentypen
Typ Key der Schlüsselwerte
auch Typ Key, im Gegensatz zu map
entspricht Key*
entspricht Key&
Typ Compare. Funktionsobjekt, das die
Sortierreihenfolge der Schlüssel festlegt
…
Weitere Typen wie Sequenz-Container
Weitere Informationen:
key_type
value_type
pointer
reference
key_compare
set-Element
Key
value_type
key_type
Weitere Informationen zum Einfügen, Suchen und Löschen von Daten finden Sie hier:
http://www.cplusplus.com/reference/stl/set/
Breymann: C++. S. 523
07.12.2012
C++ Standard Template Library (STL)
33

Documentos relacionados