Iteratoren in C++ (Iteratoren in C++), Lektion, Seite 723716
https://www.purl.org/stefan_ram/pub/iterator_c++ (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Positionen in C++ 

Unter einer Folge  von Objekten stellen wir uns eine Menge von Objekten vor, die linear angeordnet sind. Man denke etwa an eine Zeichenfolge. Dabei hat jedes Objekt der Folge einen Vorgänger und einen Nachfolger, und jedes Objekt kann von jedem anderen aus durch wiederholtes Gehen zum Nachfolger oder Vorgänger erreicht werden; ausnahmsweise darf es ein Objekt geben, das keinen Vorgänger hat, und ein Objekt, das keinen Nachfolger hat. (Dies beschreibt allerdings nur unsere Vorstellung  einer Folge, es muß nicht immer möglich sein, alle eben beschriebenen Operationen auch in einem C++ -Programm durchzuführen.)

In C++  kann eine Folge  beispielsweise aus einem Objekt der Klasse »::std::string«, der Klasse »::std::vector<T>« oder der Klasse »::std::initializer_list<T>« gewonnen werden – alles Klassen für Objekte, die eine Anordnung von Dingen darstellen. Aber auch eine Reihung  kann eine Folge liefern.

Im folgenden Beispiel einer Folge hat die linke Komponente keinen Vorgänger und die rechte keinen Nachfolger. Der Nachfolger der linken Komponente ist die mittlere Komponente und der Nachfolger der mittleren Komponente ist die rechte Komponenten. Der Vorgänger der mittlere Komponente ist die linke Komponente und der Vorgänger der rechten Komponente ist die mittlere Komponenten.

Eine Folge von drei Objekten

.---. .---. .---.
| a | | b | | a |
'---' '---' '---'

(links Mitte rechts)

Die dargestellte Folge könnte in einem Programm praktisch durch das Zeichenfolgenliteral »"aba"s« dargestellt werden. Beispiele für Folgen in C++  sind sind Zeichenfolgen, Vektoren und Reihungen.

Man sieht, daß es nicht ganz einfach ist, sich auf eine Position  in einer Folge zu beziehen. Wir können zwar von „der Komponente »b«“ sprechen, aber nicht von „der Komponente »a«“, da es zwei Komponenten mit dem Buchstaben »a« gibt. Wir können die Komponenten von Zeichenfolgen, Vektoren und Reihungen zwar als durchnumeriert ansehen, aber nicht alle Folgen in C++  erlauben es, eine Kennzahl zu verwenden, um eine bestimmte Komponente auszudrücken. Daher gibt es in C++  spezielle Werte, um Positionen in einer Folge  auszudrücken.

Eine Position  gibt eine Position  in einer Folge von Objekten an.

Der Anfang »cbegin«

Die Funktion »cbegin« ergibt die Position des Anfangs einer Folge von Objekten. Wir benötigen »#include <iterator>«.

main.cpp

#include <string>
#include <iterator> /* cbegin */
#include <initializer_list>

using namespace ::std::literals;

int main()
{ ::std::string const str{ "abc"s };
auto const p0 = cbegin( str ); }

Protokoll
(keine Ausgabe)

Die Position »p0« gibt jetzt die Position des »a« an.

Wir werden erst etwas später sehen, wofür Positionen verwendet werden können.

Man beachte die Verwendung von ADL in »cbegin( str )«. Der Typ des Argumentausdrucks ist »::std::string«. Der Name jenes Typs befindet sich im Namensraum »::std«. Daher wird in »::std« nach »cbegin« gesucht und es muß nicht »::std::cbegin( str )« geschrieben werden.

Folgen

Es gibt Typen, deren Ausdrücke die nicht  als Argument von »::std::cbegin« verwendet werden können.

main.cpp

#include <iterator>

int main()
{ auto const p0 = ::std::cbegin( 2 ); }

Protokoll (überarbeitet und übersetzt)
main.cpp: In Funktion 'int main()':
main.cpp:4:36: Fehler: keine passende Funktion für den Aufruf '::std::cbegin(int)'
{ auto const p0 = ::std::cbegin( 2 ); }
^

Wir nennen einen Ausdruck, der als Argument von »::std::cbegin« verwendet werden kann, einen Folgenausdruck, entsprechend ist sein Typ ein Folgentyp  und der Wert des Ausdrucks eine Folgenobjekt. Wenn keine Mißverständnisse zu befürchten sind, können alle drei aber auch einfach als eine Folge  bezeichnet werden.

Eine Zeichenfolge ist also eine Folge, während eine Zahl keine Folge ist.

Ein anderes mögliches, etwas technischeres Adjektiv für eine Folge wäre „const-iterabel “ (englisch: “const-iterable ”).

Ein Objekt mit einem Typ aus der Standardbibliothek ist eine Folge, wenn es entweder eine Reihung ist oder eine Elementfunktion »begin()« enthält.

Der Deckel »cend«

In C++  gibt es zu einer Folge von Objekten mehr Positionen als Objekte! Es gibt zu jedem Objekt eine Position, welche sich „direkt hinter“ jenem Objekt befindet, und zwar auch für das letzte Objekt der Folge, obwohl sich hinter diesem gar kein Objekt mehr befindet.

Positionen hinter Objekten

0 1 2 3 Objekte
.---. .---. .---.
| a | | b | | a |
'---' '---' '---'
| ^ | ^ | ^
'---' '---' '---' Weg zum Nachfolger

^ ^ ^ ^
0 1 2 3 4 Positionen

Die Position direkt hinter  dem letzten Objekt einer Folge von Objekten bezeichnen wir auch als den Deckel  jener Folge. Der Deckel gibt kein Objekt der Folge an, es ist eine Position ohne Objekt.

Die Funktion »cend« ergibt die Position des Deckels einer Objektfolge.

main.cpp

#include <iostream>
#include <ostream>
#include <string>
#include <iterator>
#include <initializer_list>

using namespace ::std::literals;

int main()

{ ::std::string s = "abc"s;
auto const pt = cend( s ); }

transcript

Die Position »pt« gibt jetzt die Position „direkt hinter“ dem Buchstaben »c« an.

Wir werden erst etwas später sehen, wofür Positionen verwendet werden können.

Anfang und Deckel

.---. .---. .---.
| a | | b | | c |
'---' '---' '---'

^ ^
cbegin cend

Positionen in Reihungen

Auch für Reihungen können Positionen erhalten werden, doch da hier das ADL nicht greift, muß dann wieder »::std« als Namensraum angegeben werden.

main.cpp

#include <initializer_list>

int main()

{ int a[]{ 1, 2, 3 };
{ auto const p0 = ::std::cbegin( a ); }
{ auto const pt = ::std::cend( a ); }}

transcript

Durch eine Verwendung von »using« können die Schreibweisen vereinheitlicht werden. (»using« kann auch in einem Block verwendet werden und gilt dann für jenen Block.)

main.cpp

#include <iostream>
#include <ostream>
#include <string>
#include <iterator>
#include <initializer_list>

using namespace ::std::literals;

int main()

{ using ::std::cbegin;
using ::std::cend;

{ ::std::string s = "abc"s;
auto const p0 = cbegin( s ); }

{ int a[]{ 1, 2, 3 };
auto const p1 = cbegin( a ); }}

transcript

Nicht-konstante Positionen (Schreibpositionen)

Die von uns oben verwendeten „konstanten“ Positionen erlauben es nicht, unter Verwendung jener Positionen in Objekt zu schreiben, dafür sind „nicht-konstante“ Indikator zu verwenden, die mit »begin« und »end« erhalten werden.

Konstante Positionen werden von »::std::cbegin« und »::std::cend« geliefert, nichtkonstante von »::std::begin« und »::std::end«.

main.cpp

#include <initializer_list>
#include <iostream>
#include <iterator>
#include <ostream>
#include <string>

using namespace ::std::literals;

int main()

{ ::std::string s = "abc"s;
{ auto const p0 = begin( s ); }
auto const pt = end( s ); }}

transcript

Positionen in Vektoren

Auch für Vektoren  können Positionen erhalten werden.

main.cpp

#include <initializer_list>
#include <vector>

int main()

{ ::std::vector< int >v { 0, 1, 2 };
{ auto const p0 = cbegin( v ); }
{ auto const pt = cend( v ); }
{ auto const p0 = begin( v ); }
{ auto const pt = end( v ); }}

transcript

Positionen in Initialisierungslistenobjekten

Auch für Initialisierungslistenobjekte  können Positionen erhalten werden.

main.cpp

#include <initializer_list>
#include <ostream>
#include <iostream>
#include <string>

int main()
{ ::std::initializer_list< char > l { 'a', 'b', 'c' };
{ auto const p0 = cbegin( l ); }
{ auto const pt = cend( l ); }
{ auto const p0 = begin( l ); }
{ auto const pt = end( l ); } }

transcript

Das Initialisierungslistenobjekte sonst wenig Zugriffsmöglichkeiten bieten (es gibt keine at-Funktion zum Zugriff auf eine Komponente), sind die Positionsfunktionen für Initialisierungslistenobjekte besonders wichtig. Wir werden allerdings erst etwas später sehen wie jene Funktionen eingesetzt werden können.

Bereiche

Ein Paar von Positionen gibt einen Bereich  an, wenn sie Positionen in ein und derselbe Liste sind und die zweite Position hinter der ersten liegt (also durch wiederholtes Gehen zum Nachfolger von der ersten Position aus erreichbar ist). Beispiel: Das Paar »cbegin( str )« und »cend( str )« gibt einen Bereich an.

Wir nennen

Ein Bereich von drei Objekten (»abc«)

.---. .---. .---.
| a | | b | | c |
'---' '---' '---'

^ ^
'-----------------'
cbegin cend

Der Deckel des Bereichs (die zweite Komponente des Bereichs) gilt nicht mehr als Teil des Bereichs, er liegt hinter  dem Bereich!

Das Paar aus der Position des »a« und der Position des »c« in der Zeichenfolge »abc« umfaßt beispielsweise nur zwei Objekte, nämlich »a« und »b«. Der Deckel, also die Position des »c« gehört nicht mehr dazu.

Ein Bereich von zwei Objekten (»ab«)

.---. .---. .---.
| a | | b | | c |
'---' '---' '---'

^ ^
'------------'

Bereiche werden oft verwendet, um Folgen von Objekten auf eine abstrakte Weise zu beschreiben, wie wir etwas später sehen werden.

Ein Bereich mit einem Objekt (»a«)

.---. .---. .---.
| a | | b | | c |
'---' '---' '---'

^ ^
'------'

Bei einem leeren Bereich ist die erste Position gleich der zweiten Position

Ein leerer Bereich (»«)

.---. .---. .---.
| a | | b | | c |
'---' '---' '---'

^
'

Wir werden erst etwas später sehen, wofür Bereiche verwendet werden können.

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723716 stefan_ram:723716 Iteratoren in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723716, slrprddef723716, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/iterator_c++