Vektoren in C++
Die Schablone »::std::vector« ähnelt der Schablone »::std::basic_string«.
Um Vektoren verwenden zu können, wird die Direktive »#include <vector>« benötigt.
main.cpp
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string> /* ::std::basic_string */
#include <vector>int main()
{ ::std::basic_string< char >s{ 'a', 'b' };
::std::cout << s.size() << '\n';
::std::cout << s.at( 0 )<< '\n';
::std::cout << s.at( 1 )<< '\n';::std::vector< char > v{ 'a', 'b' };
::std::cout << v.size() << '\n';
::std::cout << v.at( 0 )<< '\n';
::std::cout << v.at( 1 )<< '\n'; }transcript
2
a
b
2
a
b
Objekte eines Typs einer Anwendung der Schablone »::std::vector« werden auch Vektoren genannt.
Die einzelnen Objekt in einem Vektor nennen wir auch die Komponenten des Vektors.
Ein Vektor kann ähnlich wie eine Zeichenfolge verwendet werden. Zwei wichtige Unterschiede sind jedoch:
- Der Vektor kann nicht mit »( ::std::cout << p )« als Ganzes ausgegeben werden.
- Während die Schablone »::std::basic_string« für die Anwendung auf Typen gedacht ist, die Schriftzeichen darstellen, kann ein Vektor Objekte fast beliebiger Typen enthalten.
Das folgende Beispiel zeigt ein Vektor mit int-Objekten und einen Vektor mit einem ::std::string-Objekt.
main.cpp
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
#include <vector> /* ::std::vector */using namespace ::std::literals;
int main()
{ { ::std::vector< int >v{ 0, 1, 2 };
::std::cout << v.at( 0 )<< '\n';
::std::cout << v.at( 1 )<< '\n';
::std::cout << v.at( 2 )<< '\n';
} /* Hier wird der Speicher von v wieder freigegeben */{ ::std::vector< int >v{ 0, 1 };
::std::cout << " " << v.at( 0 )<< '\n';
::std::cout << " " << v.at( 1 )<< '\n'; }{ ::std::vector< int >v{ 0 };
::std::cout << " " << v.at( 0 )<< '\n'; }{ ::std::vector< int >v {}; /* leerer Vektor */ }
{ ::std::vector< ::std::string >v{ "b"s };
::std::cout << v.at( 0 )<< '\n'; }}Protokoll
0
1
2
0
1
0
b
Die bei Facebook am häufigsten verwendeten Vektoren sind
- Vektoren von int-Objekten,
- Vektoren von ::std::string-Objekten und
- Vektoren, die andere Vektoren enthalten.
(Quelle: Video: Nicholas Ormrod: “The strange details of std::string at Facebook ”, Cppcon 2016 )
Änderungen via »at«
Viele Behälter, wie beispielsweise Vektoren, erlauben es, ihre Komponenten durch eine Zuweisung an einen at-Aufruf zu ändern.
Jedoch kann eine Funktion einen ihr „übergebenen“ Vektor nicht ändern, da der Parametervektor eine unabhängige Kopie des Argumentvektors darstellt. Die Situation ist hier genau wie bei int-Objekten. Wie solche Änderungen doch möglich sind, wird erst später im Kurs gezeigt werden.
main.cpp
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
#include <vector> /* ::std::vector */using namespace ::std::literals;
static void f( ::std::vector< int >v ) { v.at( 0 )= 7; }
int main()
{ ::std::vector< int >v{ 0, 1, 2 };
v.at( 0 )= 4;
::std::cout << v.at( 0 )<< '\n';
f( v );
::std::cout << v.at( 0 )<< '\n'; }transcript
4
4
Man sagt auch, »v.at( 0 )« sei ein “lvalue ”, um auszudrücken, daß es auch auf der linken Seite eines Zuweisungsoperators verwendet werden darf.
Anfügen via »push_back«
Die am häufigsten verwendeten Methoden von Vektoren sind vermutlich »size()«, »push_back«/»emplace_back« und »at()«.
Mit »push_back« wird ein Objekt an das Ende eines Vektors angefügt, und mit »size()« wird die Anzahl der in einem Vektor enthaltenen Komponenten ermittelt.
main.cpp
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
#include <vector> /* ::std::vector */using namespace ::std::literals;
int main()
{ ::std::vector< int >v;
::std::cout << v.size()<< '\n';
v.push_back( 3 );
::std::cout << v.size()<< '\n';
::std::cout << v.at( 0 )<< '\n'; }transcript
0
1
3
Anfügen via »emplace_back«
main.cpp
#include <algorithm>
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
#include <vector>int main()
{ ::std::vector< ::std::pair< int, int >>v;
v.emplace_back( 0, 1 ); /* "Weiterreichen" der Argumente */
v.emplace_back( 2, 3 ); /* an den Konstruktor von pair. */
::std::cout << v.at( 0 ).first << '\n';
::std::cout << v.at( 0 ).second << '\n';
::std::cout << v.at( 1 ).first << '\n';
::std::cout << v.at( 1 ).second << '\n'; }- Protokoll
0
1
2
3main.cpp
#include <algorithm>
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
#include <vector>int main()
{ ::std::vector< ::std::pair< int, int >>v;
::std::pair< int, int > const p{ 4, 5 };
::std::pair< int, int > const q{ 6, 7 };
v.push_back( p ); /* push_back hat immer genau */
v.push_back( q ); /* ein Argument. */
::std::cout << v.at( 0 ).first << '\n';
::std::cout << v.at( 0 ).second << '\n';
::std::cout << v.at( 1 ).first << '\n';
::std::cout << v.at( 1 ).second << '\n'; }- Protokoll
4
5
6
7
emplace_back erzeugt das Paar direkt im Vektor, bei push_back wird ein schon vorhandenes Paar in den Vektor kopiert, das eventuell erst vorher in einem extra Schritt erzeugt worden sein muß.
Übungsaufgaben
/ Übungsaufgabe
Ergänzen Sie die folgenden Programmschablone an den mit einer Ellipse »…« gekennzeichneten Stellen, so daß die Funktion »print« den ihr übergebenen Vektor wie unter dem Programm gezeigt einmal vorwärts und einmal rückwärts ausgibt. Hierfür können Elementfunktionen der Klasse »::std::vector< char >« und Schleifen verwendet werden.
main.cpp
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <vector> /* ::std::vector */void print_forward( ::std::vector< char > const v )
{ … }void print_reverse( ::std::vector< char > const v )
{ … }void print( ::std::vector< char > const v )
{ print_forward( v );
print_reverse( v ); }int main()
{ { ::std::vector< char >v{ 'a', 'b' }; print( v ); }
{ ::std::vector< char >v{ 'a', 'b', 'c' }; print( v ); }}transcript
ab
ba
abc
cba
Ersetzen Sie die Funktionen durch Zusatzanforderung Funktionsschablonen, so daß sie auch für »::std::vector< int >« und »::std::vector< double >« verwendet werden können.
/ Übungsaufgabe
Schreiben Sie eine Funktion »sum«, die einen Vektor von int-Werten als Argument akzeptiert und unter Verwendung einer Schleife die Summe aller Werte des Vektors zurückgibt. Hierzu können Sie die Elementfunktionen »size« und »at« verwenden.
main.cpp
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <vector> /* ::std::vector */…
int main()
{ ::std::vector< int >v { 1, 2, 3 };
::std::cout << sum( v ) << '\n'; /* 6 */}transcript
6
Ersetzen Sie die Funktion » Zusatzanforderungsum« durch eine Funktionsschablone »sum«, so daß sie auch für »::std::vector< double >« verwendet werden kann.