Eine Tour durch C++ - Bjarne Stroustrup - E-Book

Eine Tour durch C++ E-Book

Bjarne Stroustrup

0,0

Beschreibung

  • Die neuesten Sprachfeatures im Überblick
  • Verfasst vom Entwickler von C++
  • Übersetzung der 3. Auflage

Dieses Buch bietet erfahrenen Programmierern einen praktischen Überblick über C++20 nach ISO-Standard und damit ein klares Verständnis für den Einsatz von modernem C++. Anhand vieler Codebeispiele und hilfreicher Praxistipps wird ein Großteil der Hauptfeatures der Sprache sowie der Standardbibliothek behandelt, die für den effektiven Einsatz unverzichtbar sind.

Stroustrup stellt die einzelnen Sprachfeatures von C++ vor und zeigt, wie sie im Kontext der unterstützten Programmierstile eingesetzt werden, beispielsweise der objektorientierten oder generischen Programmierung. Seine Tour beginnt mit den Grundlagen und setzt den Fokus anschließend auf fortgeschrittene Techniken, wobei er insbesondere auf die neueren Sprach-features eingeht.

Dieses Buch deckt zahlreiche Features ab, die mit C++20 neu eingeführt wurden, darunter Module, Konzepte, Koroutinen und Bereiche. Selbst einige schon jetzt verfügbare Komponenten, die nicht vor C++23 in den Standard integriert werden sollen, werden vorgestellt.

Wenn Sie bereits Programmierkenntnisse in C++ oder einer anderen Sprache haben, ist dies die kompakteste und verständlichste Einführung, um die Besonderheiten und Vorteile von modernem C++ kennenzulernen.

Aus dem Inhalt
  • Die Grundlagen: Funktionen, Referenzen, Zeiger und mehr
  • Benutzerdefinierte Typen
  • Modularität
  • Fehlerbehandlung
  • Klassen
  • Operationen
  • Templates
  • Konzepte und generische Programmierung
  • Die Standardbibliothek
  • Strings und reguläre Ausdrücke
  • Streams
  • Algorithmen
  • Bereiche (Ranges)
  • Zeiger und Container
  • Utilities
  • Numerik
  • Nebenläufigkeit
  • Zahlreiche Ratschläge für die effektive Programmierung aus den »C++ Core Guidelines«

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern
Kindle™-E-Readern
(für ausgewählte Pakete)

Seitenzahl: 474

Veröffentlichungsjahr: 2023

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Inhaltsverzeichnis
Impressum
Einleitung
Danksagungen
Über die Fachkorrektoren der deutschen Ausgabe
Kapitel 1: Die Grundlagen
1.1 Einführung
1.2 Programme
1.2.1 ‌Hello, World!
1.3 ‌Funktionen
1.4 Typen, Variablen und Arithmetik
1.4.1 Rechenoperatoren
1.4.2 Initialisierung
1.5 Gültigkeitsbereich und ‌Lebensdauer
1.6 ‌Konstanten
1.7 Zeiger, ‌Arrays und ‌Referenzen
1.7.1 Der ‌Null-Pointer
1.8 Bedingungen prüfen
1.9 Auf Hardware abbilden
1.9.1 ‌Zuweisung
1.9.2 ‌Initialisierung
1.10 Ratschläge
Kapitel 2: Benutzerdefinierte Typen
2.1 Einführung
2.2 Strukturen
2.3 Klassen
2.4 Aufzählungen
2.5 Unions
2.6 Ratschläge
Kapitel 3: Modularität
3.1 Einführung
3.2 Separates Kompilieren
3.2.1 Header-Dateien
3.2.2 Module
3.3 Namensräume
3.4 Funktionsargumente und Rückgabewerte
3.4.1 Argumentübergabe
3.4.2 Werterückgabe
3.4.3 Rückgabetyp ableiten
3.4.4 Suffix-Rückgabetyp
3.4.5 Strukturierte Bindung
3.5 Ratschläge
Kapitel 4: Fehlerbehandlung
4.1 Einführung
4.2 Exceptions
4.3 Invarianten
4.4 Alternativen für die Fehlerbehandlung
4.5 Assertions
4.5.1 assert()
4.5.2 Statische Assertionen
4.5.3 noexcept
4.6 Ratschläge
Kapitel 5: Klassen
5.1 Einführung
5.1.1 Klassen
5.2 Konkrete Typen
5.2.1 Ein arithmetischer Typ
5.2.2 Ein Container
5.2.3 Container initialisieren
5.3 Abstrakte Typen
5.4 Virtuelle Funktionen
5.5 Klassenhierarchien
5.5.1 Vorteile von Hierarchien
5.5.2 Die Navigation in einer Hierarchie
5.5.3 Ressourcenlecks vermeiden
5.6 Ratschläge
Kapitel 6: Notwendige Operationen
6.1 Einführung
6.1.1 Notwendige Operationen
6.1.2 Konvertierungen
6.1.3 Member-Initialisierer
6.2 Kopieren und Verschieben
6.2.1 Container kopieren
6.2.2 Container verschieben
6.3 Ressourcenverwaltung
6.4 Operatoren überladen
6.5 Konventionelle Operationen
6.5.1 Vergleiche (Relationale Operatoren)
6.5.2 Container-Operationen
6.5.3 Iteratoren und »smarte Zeiger«
6.5.4 Eingabe- und Ausgabeoperationen
6.5.5 swap()
6.5.6 hash<>
6.6 Benutzerdefinierte Literale
6.7 Ratschläge
Kapitel 7: Templates
7.1 Einführung
7.2 Parametrisierte Typen
7.2.1 Beschränkte Template-Argumente
7.2.2 Wert-Template-Argumente
7.2.3 Deduktion von Template-Argumenten
7.3 Parametrisierte Operationen
7.3.1 Funktions-Templates
7.3.2 Funktionsobjekte
7.3.3 Lambda-Ausdrücke
7.4 Template-Mechanismen
7.4.1 Variablen-Templates
7.4.2 Aliasse
7.4.3 Compile-Zeit-if
7.5 Ratschläge
Kapitel 8: Konzepte und generische Programmierung
8.1 Einführung
8.2 Konzepte
8.2.1 Verwendung von Konzepten
8.2.2 Konzeptbasiertes Überladen
8.2.3 Gültiger Code
8.2.4 Definition von Konzepten
8.2.5 Konzepte und auto
8.2.6 Konzepte und Typen
8.3 Generische Programmierung
8.3.1 Verwendung von Konzepten
8.3.2 Abstraktion mittels Templates
8.4 Variadische Templates
8.4.1 Fold-Ausdrücke
8.4.2 Argumente weitergeben
8.5 Modell der Template-Kompilierung
8.6 Ratschläge
Kapitel 9: Überblick über die Bibliothek
9.1 Einführung
9.2 Komponenten der Standardbibliothek
9.3 Organisation der Standardbibliothek
9.3.1 Namensräume
9.3.2 Der Namensraum ranges
9.3.3 Module
9.3.4 Header
9.4 Ratschläge
Kapitel 10: Strings und reguläre Ausdrücke
10.1 Einführung
10.2 Strings
10.2.1 Die Implementierung von string
10.3 String-Views
10.4 Reguläre Ausdrücke
10.4.1 Suche
10.4.2 Notation regulärer Ausdrücke
10.4.3 Iteratoren
10.5 Ratschläge
Kapitel 11: Eingabe und Ausgabe
11.1 Einführung
11.2 Ausgabe
11.3 Eingabe
11.4 I/O-Status
11.5 Ein-/Ausgabe benutzerdefinierter Typen
11.6 Ausgabeformatierung
11.6.1 Stream-Formatierung
11.6.2 Formatierung im printf()-Stil
11.7 Streams
11.7.1 Standard-Streams
11.7.2 Datei-Streams
11.7.3 String-Streams
11.7.4 Speicher-Streams
11.7.5 Synchronisierte Streams
11.8 Ein-/Ausgaben im C-Stil
11.9 Dateisystem
11.9.1 Pfade
11.9.2 Dateien und Verzeichnisse
11.10 Ratschläge
Kapitel 12: Container
12.1 Einführung
12.2 vector
12.2.1 Elemente
12.2.2 Bereichsüberprüfung
12.3 list
12.4 forward_list
12.5 map
12.6 unordered_map
12.7 Allokatoren
12.8 Ein Überblick über Container
12.9 Ratschläge
Kapitel 13: Algorithmen
13.1 Einführung
13.2 Verwendung von Iteratoren
13.3 Iterator-Typen
13.3.1 Stream-Iteratoren
13.4 Verwendung von Prädikaten
13.5 Überblick über Algorithmen
13.6 Parallele Algorithmen
13.7 Ratschläge
Kapitel 14: Bereiche (Ranges)
14.1 Einführung
14.2 Views
14.3 Generatoren
14.4 Pipelines
14.5 Überblick über Konzepte
14.5.1 Typkonzepte
14.5.2 Iterator-Konzepte
14.5.3 Bereichskonzepte
14.6 Ratschläge
Kapitel 15: Zeiger und Container
15.1 Einführung
15.2 Zeiger
15.2.1 unique_ptr und shared_ptr
15.2.2 span
15.3 Container
15.3.1 array
15.3.2 bitset
15.3.3 pair
15.3.4 tuple
15.4 Alternativen
15.4.1 variant
15.4.2 optional
15.4.3 any
15.5 Ratschläge
Kapitel 16: Utilities
16.1 Einführung
16.2 Zeit
16.2.1 Uhren
16.2.2 Kalender
16.2.3 Zeitzonen
16.3 Funktionsanpassung
16.3.1 Lambdas als Adapter
16.3.2 mem_fn()
16.3.3 function
16.4 Typfunktionen
16.4.1 Typprädikate
16.4.2 Bedingte Eigenschaften
16.4.3 Typgeneratoren
16.4.4 Assoziierte Typen
16.5 source_location
16.6 move() und forward()
16.7 Bitmanipulation
16.8 Ein Programm beenden
16.9 Ratschläge
Kapitel 17: Numerik
17.1 Einführung
17.2 Mathematische Funktionen
17.3 Numerische Algorithmen
17.3.1 Parallele numerische Algorithmen
17.4 Komplexe Zahlen
17.5 Zufallszahlen
17.6 Vektorarithmetik
17.7 Numerische Grenzen
17.8 Typ-Aliasse
17.9 Mathematische Konstanten
17.10 Ratschläge
Kapitel 18: Nebenläufigkeit
18.1 Einführung
18.2 Tasks und thread
18.2.1 Argumente übergeben
18.2.2 Ergebnisse zurückgeben
18.3 Daten gemeinsam nutzen
18.3.1 mutexe und Locks
18.3.2 atomic
18.4 Warten auf Ereignisse
18.5 Kommunizierende Tasks
18.5.1 future und promise
18.5.2 packaged_task
18.5.3 async()
18.5.4 Einen Thread stoppen
18.6 Koroutinen
18.6.1 Kooperatives Multitasking
18.7 Ratschläge
Kapitel 19: Geschichte und Kompatibilität
19.1 Geschichte
19.1.1 Chronik
19.1.2 Die frühen Jahre
19.1.3 Die ISO-C++-Standards
19.1.4 Standards und Stil
19.1.5 Verwendung von C++
19.1.6 Das C++-Modell
19.2 Die Entwicklung der Merkmale von C++
19.2.1 Sprachmerkmale von C++11
19.2.2 Sprachmerkmale von C++14
19.2.3 Sprachmerkmale von C++17
19.2.4 Sprachmerkmale von C++20
19.2.5 Komponenten der C++11-Standardbibliothek
19.2.6 Komponenten der C++14-Standardbibliothek
19.2.7 Komponenten der C++17-Standardbibliothek
19.2.8 Komponenten der C++20-Standardbibliothek
19.2.9 Entfernte und veraltete Funktionsmerkmale
19.3 C/C++-Kompatibilität
19.3.1 C und C++ sind Geschwister
19.3.2 Kompatibilitätsprobleme
19.4 Ratschläge
Anhang A: module std
A.1 Einführung
A.2 Benutzen Sie, was Ihre Implementierung zu bieten hat
A.3 Benutzen Sie Header
A.4 Machen Sie sich Ihr eigenes module std
A.5 Ratschläge
Anhang B: Literaturverzeichnis
B.1 Literaturhinweise

Bjarne Stroustrup

Eine Tour durch C++

Der praktische Leitfaden für modernes C++

Übersetzung aus dem Englischen von Kathrin Lichtenberg

Impressum

Bibliografische Information der Deutschen Nationalbibliothek Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

ISBN 978-3-7475-0627-1 1. Auflage 2023

www.mitp.de E-Mail: [email protected] Telefon: +49 7953 / 7189 - 079 Telefax: +49 7953 / 7189 - 082

© 2023 mitp Verlags GmbH & Co. KG

Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften.

Dieses E-Book verwendet das EPUB-Format und ist optimiert für die Nutzung mit Apple Books auf dem iPad von Apple. Bei der Verwendung von anderen Readern kann es zu Darstellungsproblemen kommen.

Der Verlag räumt Ihnen mit dem Kauf des E-Books das Recht ein, die Inhalte im Rahmen des geltenden Urheberrechts zu nutzen. Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlags unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen Systemen.

Der Verlag schützt seine E-Books vor Missbrauch des Urheberrechts durch ein digitales Rechtemanagement. Bei Kauf im Webshop des Verlages werden die E-Books mit einem nicht sichtbaren digitalen Wasserzeichen individuell pro Nutzer signiert. Bei Kauf in anderen E-Book-Webshops erfolgt die Signatur durch die Shopbetreiber. Angaben zu diesem DRM finden Sie auf den Seiten der jeweiligen Anbieter.

Lektorat: Janina Bahlmann Sprachkorrektorat: Philipp Hasper, Conny Lichtenberg Fachkorrektorat: Petra Heubach-Erdmann Covergestaltung: Christian Kalkert Coverbild: Marco Pregnolato (Unsplash.com: @marco_pregnolato) Satz: III-satz, Kiel, www.drei-satz.deelectronic publication: III-satz, Kiel, www.drei-satz.de

Einleitung

Was auch immer du lehren wirst, fasse dich kurz.– Horaz, Ars poetica 335

C++ fühlt sich an wie eine neue Sprache. Das heißt, man kann Ideen heute deutlicher, leichter und direkter ausdrücken als in C++98 oder C++11. Außerdem werden die daraus entstehenden Programme besser vom Compiler überprüft und laufen schneller.

Dieses Buch bietet Ihnen einen Überblick über das C++, das durch C++20, den aktuellen ISO-C++-Standard, definiert und durch die wichtigsten Anbieter von C++ implementiert wird. Darüber hinaus werden eine Reihe von Bibliothekskomponenten erwähnt, die momentan schon in Gebrauch sind, aber erst mit C++23 in den Standard aufgenommen werden sollen.

Wie andere moderne Sprachen ist C++ umfangreich und es sind viele Bibliotheken erforderlich, um es effektiv benutzen zu können. Dieses recht schmale Buch soll erfahrenen Programmierern eine Vorstellung davon vermitteln, was modernes C++ ausmacht. Es behandelt die wichtigsten Eigenschaften der Sprache sowie die wichtigsten Komponenten der Standardbibliothek. Es ist möglich, das Buch in ein oder zwei Tagen durchzulesen, aber natürlich braucht man mehr als zwei Tage, um zu lernen, gutes C++ zu schreiben. Das Ziel ist hier aber nicht, C++ zu beherrschen. Stattdessen erhalten Sie einen Überblick, zentrale Beispiele und eine gute Ausgangsbasis.

Ich gehe davon aus, dass Sie bereits programmiert haben. Falls nicht, sollten Sie zuerst ein Lehrbuch wie Programming: Principles and Practice Using C++ (Second edition) [Stroustrup, 2014] lesen, bevor Sie hier weitermachen[1]. Selbst wenn Sie programmiert haben, könnten die von Ihnen benutzte Sprache oder die von Ihnen geschriebenen Anwendungen sich grundlegend von dem Stil des C++ unterscheiden, der hier vorgestellt wird.

Stellen Sie sich eine Besichtigungstour in einer Stadt wie Kopenhagen oder New York vor. In nur wenigen Stunden erhaschen Sie einen kurzen Blick auf die wichtigsten Sehenswürdigkeiten, hören ein paar Anekdoten und bekommen Vorschläge, was Sie als Nächstes tun könnten. Sie kennen die Stadt nach einer solchen Rundfahrt nicht. Sie verstehen nicht alles, was Sie gesehen und gehört haben; manche der Geschichten klingen vermutlich seltsam oder sogar unglaubwürdig. Sie kennen auch nicht die offiziellen und inoffiziellen Regeln, die das Leben in der Stadt bestimmen. Um eine Stadt wirklich kennenzulernen, müssen Sie darin leben, am besten für viele Jahre. Mit ein bisschen Glück haben Sie allerdings einen Überblick gewonnen, ein Gefühl dafür, was so besonders an der Stadt ist, und können sich vielleicht vorstellen, was für Sie interessant sein könnte. Nach der Tour kann die eigentliche Entdeckungsreise beginnen.

Diese Tour stellt die wichtigsten C++-Spracheigenschaften vor, die Programmierparadigmen unterstützen, wie die objektorientierte und die generische Programmierung. Sie versucht nicht, einen detaillierten, alle Funktionen und Eigenschaften einschließenden Blick auf die Sprache zu liefern – dieses Buch soll kein Referenzhandbuch sein. In bester Lehrbuchtradition versuche ich, ein Feature zu erklären, bevor ich es benutze, aber das ist nicht immer möglich und nicht jeder liest einen Text streng sequenziell. Ich erwarte von meinen Leserinnen und Lesern eine gewisse technische Reife. Sie sind eingeladen, die Querverweise und den Index zu benutzen.

Auch die Standardbibliotheken werden auf dieser Tour nicht allumfassend, sondern nur beispielhaft vorgestellt. Suchen Sie bei Bedarf selbst nach zusätzlichen und unterstützenden Materialien. Das C++-Ökosystem bietet viel mehr als nur die Möglichkeiten, die der ISO-Standard mitbringt (z. B. Bibliotheken, Build-Systeme, Analysewerkzeuge und Entwicklungsumgebungen). Es gibt im Web eine Unmenge an Material (von durchaus unterschiedlicher Qualität). Die Tutorial- und Überblicksvideos von Konferenzen wie CppCon und Meeting C++ werden viele Leserinnen und Leser sicher überaus nützlich finden. Für die technischen Details der Sprache und Bibliothek, die vom ISO-C++-Standard angeboten werden, empfehle ich [Cppreference]. Wenn ich zum Beispiel eine Funktion oder Klasse der Standardbibliothek erwähne, kann deren Definition leicht nachgeschlagen werden. Und in der Dokumentation lassen sich dann auch viele weitere, damit verwandte Möglichkeiten finden.

Diese Tour präsentiert C++ als geschlossenes Ganzes. Entsprechend gebe ich nur selten an, ob Sprachmerkmale zu C, C++98 oder späteren ISO-Standards gehören. Solche Informationen finden Sie in Kapitel 19 (Geschichte und Kompatibilität). Ich konzentriere mich auf die Grundlagen und versuche, mich kurz zu fassen, konnte aber dennoch nicht der Versuchung widerstehen, neue Eigenschaften, wie Module (§3.2.2), Konzepte (§8.2) und Coroutinen (§18.6), ausführlicher zu behandeln. Dass der Schwerpunkt eher auf neueren Entwicklungen liegt, wird auch die Neugier vieler Leserinnen und Leser befriedigen, die bereits ältere Versionen von C++ kennen.

Das Referenzhandbuch oder der Standard einer Sprache hält einfach nur fest, was gemacht werden kann. Programmiererinnen und Programmierer wollen jedoch oft lieber lernen, wie sie die Sprache gut einsetzen können. Diesem Aspekt wird durch die Auswahl der behandelten Themen Genüge getan – zum Teil im Text, vor allem aber in den Abschnitten mit den Ratschlägen. Weitere Hinweise dazu, was gutes, modernes C++ ausmacht, können Sie in den C++ Core Guidelines [Stroustrup, 2015] finden. Die Core Guidelines eignen sich hervorragend, um die in diesem Buch vorgestellten Ideen weiter zu erkunden. Sie werden vermutlich eine bemerkenswerte Ähnlichkeit zwischen der Formulierung und sogar der Nummerierung der Ratschläge in den Core Guidelines und diesem Buch bemerken. Ein Grund dafür ist, dass die erste Auflage von A Tour of C++ eine wesentliche Quelle für die ersten Core Guidelines war.

Danksagungen

Ein Dank geht an alle, die geholfen haben, die früheren Ausgaben von A Tour of C++ fertigzustellen und zu korrigieren, vor allem die Studentinnen und Studenten in meinem »Design Using C++«-Kurs an der Columbia University. Ich danke Morgan Stanley, dass sie mir die Zeit gegeben hat, diese dritte Auflage zu verfassen. Danke an Chuck Allison, Guy Davidson, Stephen Dewhurst, Kate Gregory, Danny Kalev, Gor Nishanov und J. C. van Winkel für das Begutachten des Buches und die vielen Verbesserungsvorschläge.

Die Originalausgabe dieses Buches wurde vom Autor mit troff gesetzt, die verwendeten Makros stammten von Brian Kernighan.

Manhattan, New YorkBjarne Stroustrup

Über die Fachkorrektoren der deutschen Ausgabe

Philipp Hasper ist Gründer eines Augmented-Reality-Startups und erfahren in der akademischen und industriellen Entwicklung von KI-Technologien. Er entwickelt mit C++, Java, Python und Typescript und hat bei zahlreichen Open-Source-Projekten mitgewirkt. Von ihm stammt auch das Buch C++ Schnelleinstieg, das im mitp-Verlag erschienen ist.

Conny Lichtenberg widmete sich nach seinem Informatikstudium für viele Jahre in seiner eigenen kleinen Firma dem informationstechnischen Allerlei – Systementwurf, Programmierung, Consulting –, bevor er sich neue Herausforderungen suchte und nun Softwareprojekte betreut. Seine Spezialität ist das Werkeln auf der Kommandozeile und er hat den Ehrgeiz, möglichst viele Probleme mit kunstvoll konstruierten regulären Ausdrücken und Pipelines zu lösen.

[1] Anm. zur Übersetzung: Auch im deutschsprachigen Raum sind geeignete Lehrbücher erschienen, beispielsweise C++ Schnelleinstieg von (Hasper, 2021) oder C++ lernen und professionell anwenden (Prinz/Kirch, 2022).

Kapitel 1: Die Grundlagen

The first thing we do, let’skill all the language lawyers.– Henry VI, Part II

1.1  Einführung

Dieses Kapitel präsentiert ganz formlos die Notation von C++, das Speicher- und Berechnungsmodell von C++ sowie die grundlegenden Mechanismen, nach denen Code zu einem Programm zusammengefügt wird. Dies sind die Komponenten, die man vor allem in C sieht und die einen Programmierstil bilden, der als ‌‌prozedurale Programmierung bezeichnet wird.

1.2  Programme

C++ ist eine kompilierte Sprache. Damit ein Programm ausgeführt werden kann, muss sein Quelltext durch einen Compiler verarbeitet werden. Dabei werden Objektdateien erzeugt, die dann ein Linker zu einem ausführbaren Programm kombiniert. Ein C++-Programm besteht typischerweise aus vielen Quellcodedateien (meist einfach ‌Quelldateien genannt).

Ein ausführbares Programm wird für eine bestimmte Hardware/System-Kombination erzeugt; es kann nicht von z. B. einem Android-Gerät auf einen Windows-PC übertragen werden. Wenn es um die ‌‌Portabilität von C++-Programmen geht, dann meinen wir üblicherweise die Portabilität des Quellcodes; das heißt, dass der Quellcode erfolgreich auf einer Vielzahl von Systemen kompiliert und ausgeführt werden kann.

Der ‌ISO-C++-Standard definiert zwei Arten von Entitäten:

Elemente der Kernsprache, wie integrierte Typen (z. B. char und int) und Schleifen (z. B. for- und while-Anweisungen)

Komponenten der Standardbibliothek, wie etwa Container (z. B. vector und map) und I/O-Operationen (z. B. << und getline())

Bei den Komponenten der ‌‌Standardbibliothek handelt es sich um völlig normalen C++-Code, der von jeder C++-Implementierung bereitgestellt wird. Das heißt, die C++-Standardbibliothek kann selbst in C++ implementiert werden, was auch so ist (mit sehr geringfügigem Einsatz von Maschinencode für Dinge wie thread-Kontextwechsel). Das impliziert, dass C++ für die anspruchsvollsten Aufgaben im Bereich der Systemprogrammierung ausreichend ausdrucksstark und effizient ist.

C++ gehört zu den statisch ‌typisierten Sprachen. Das heißt, der Typ jeder Entität (wie etwa Objekt, Wert, Name und Ausdruck) muss dem Compiler an der Stelle bekannt sein, an der sie benutzt wird. Der Typ eines Objekts bestimmt die Menge der Operationen, die darauf angewendet werden können, sowie seine Anordnung im Speicher.

1.2.1  ‌Hello, World!

Das kleinstmögliche C++-Programm ist

int main(){} // das kleinstmögliche C++-Programm

Es definiert eine Funktion namens ‌main(), die keine Argumente entgegennimmt und nichts tut.

Geschweifte Klammern, ‌{}, drücken in C++ eine Gruppierung aus. Hier kennzeichnen sie den Anfang und das Ende des Funktionskörpers. Der doppelte Schrägstrich, //, startet einen Kommentar, der bis zum Zeilenende reicht. Ein Kommentar ist für die menschlichen Leserinnen und Leser vorgesehen; der Compiler ignoriert Kommentare.

Jedes C++-Programm muss genau eine globale Funktion namens main() besitzen. Das Programm startet, indem es diese Funktion ausführt. Der Integer-Wert int, der von main() zurückgegeben wird, falls er vorhanden ist, ist der Rückgabewert des Programms an »das System«. Wird kein Wert zurückgegeben, erhält das System einen Wert, der einen erfolgreichen Abschluss des Programms signalisiert. Ist der von main() zurückgegebene Wert ungleich null, bedeutet dies ein Fehlschlagen des Programms. Nicht alle Betriebssysteme und Ausführungsumgebungen machen Gebrauch von diesem Rückgabewert: Linux/Unix-Systeme tun es, Windows-Umgebungen dagegen nur selten.

Üblicherweise erzeugt ein Programm irgendeine Ausgabe. Hier ist ein Programm, das Hello, World! schreibt:

import std;int main(){ std::cout << "Hello, World!\n";}

Die Zeile import std; weist den Compiler an, die Deklarationen der Standardbibliothek zur Verfügung zu stellen. Ohne diese Deklarationen wäre der Ausdruck

std::cout << "Hello, World!\n"

sinnlos. Der Operator ‌‌<< (»ausgeben«) schreibt sein zweites Argument auf sein erstes. In diesem Fall wird das String-Literal "Hello, World!\n" auf den Standard-Ausgabe-Stream std::cout geschrieben. Ein String-Literal ist eine Folge von Zeichen, die von doppelten Anführungszeichen umgeben sind. In einem String-Literal kennzeichnet der Backslash ‌\ gefolgt von einem anderen Zeichen ein einzelnes »Sonderzeichen«. Hier ist ‌\n das Newline-Zeichen. Es werden also die Zeichen Hello, World! geschrieben, gefolgt von einem Newline, also dem Steuerzeichen für eine neue Zeile.

‌std:: gibt an, dass der Name (Bezeichner) ‌cout im Namensraum der Standardbibliothek (§3.3) zu finden ist. Ich lasse das std:: normalerweise weg, wenn es um Standardeigenschaften geht. §3.3 zeigt, wie man Namen aus einem Namensraum auch ohne explizite Qualifizierung sichtbar machen kann.

Die Direktive ‌import ist neu in C++20. Es ist noch nicht im Standard verankert, dass die gesamte Standardbibliothek als Modul std vorhanden ist. Das wird in §3.2.2 erklärt. Falls Sie Probleme mit import std; haben, probieren Sie das altmodische und herkömmliche

#include <iostream> // bindet die Deklarationen für die // I/O-Stream-Bibliothek einint main(){ std::cout << "Hello, World!\n";}

Das wird in §3.2.1 erklärt und hat in allen C++-Implementierungen seit 1998 funktioniert (§19.1.1).

Im Prinzip wird der gesamte ausführbare Code in ‌Funktionen gepackt und direkt oder indirekt aus main() heraus aufgerufen. Zum Beispiel:

import std; // importiert die Deklarationen für die // Standardbibliothekusing namespace std; // macht die Namen aus std auch ohne // std:: sichtbar (§3.3)double square(double x) // quadriert eine Gleitkommazahl mit doppelter // Genauigkeit{ return x*x;}void print_square(double x){ cout << "das Quadrat von " << x << " ist " << square(x) << "\n";}int main(){ print_square(1.234) // Ausgabe: das Quadrat von 1,234 ist 1,52276}

Der »Rückgabetyp« ‌void zeigt an, dass die Funktion keinen Wert zurückgibt.

1.10  Ratschläge

Die Ratschläge, die Sie hier sehen, sind den C++ Core Guidelines [Stroustrup, 2015][1] entnommen. Verweise auf Guidelines sehen so aus: [CG: ES.23], womit die 23. Regel im Expressions and Statement gemeint wäre. Im Allgemeinen bietet eine solche Core Guideline weitere Erklärungen und Beispiele.

Keine Panik! Alles wird im Laufe der Zeit klarer; §1.1; [CG: In.0].

Benutzen Sie nicht ausschließlich die integrierten Features. Viele grundlegende (integrierte) Features verwendet man normalerweise am besten indirekt durch Bibliotheken, wie die ISO-C++-Standardbibliothek (Kapitel 9–Kapitel 18); [CG: P.13].

Binden Sie die benötigten Bibliotheken mit #include oder (vorzugsweise) import ein, um das Programmieren zu vereinfachen; §1.2.1.

Sie müssen nicht jede Einzelheit von C++ kennen, um gute Programme zu schreiben.

Konzentrieren Sie sich auf Programmiertechniken, nicht auf Spracheigenschaften.

Der ISO-C++-Standard ist die entscheidende Instanz bei Fragen und Problemen zur Sprachdefinition; §19.1.3; [CG: P.2].

»Verpacken« Sie sinnvolle Operationen in Funktionen mit sorgfältig ausgewählten Namen; §1.3; [CG: F.1].

Eine Funktion sollte eine einzige logische Operation ausführen; §1.3; [CG: F.2].

Fassen Sie sich bei den Funktionen kurz; §1.3; [CG: F.3].

Verwenden Sie das Überladen, wenn Funktionen konzeptuell die gleiche Aufgabe mit unterschiedlichen Typen ausführen; §1.3.

Falls eine Funktion zum Zeitpunkt des Kompilierens ausgewertet werden darf, deklarieren Sie sie mit constexpr; §1.6; [CG: F.4].

Falls eine Funktion zum Zeitpunkt des Kompilierens ausgewertet werden muss, deklarieren Sie sie mit consteval; §1.6.

Falls eine Funktion keine Nebeneffekte haben darf, deklarieren Sie sie mit constexpr oder consteval; §1.6; [CG: F.4].

Entwickeln Sie Verständnis dafür, wie die Grundelemente der Sprache auf die Hardware abgebildet werden; §1.4, §1.7, §1.9, §2.3, §5.2.2, §5.4.

Nutzen Sie Trennzeichen, um große Literale besser lesbar zu machen; §1.4; [CG: NL.11].

Vermeiden Sie komplizierte Ausdrücke; [CG: ES.40].

Vermeiden Sie verengende Konvertierungen; §1.4.2; [CG: ES.46].

Minimieren Sie den Gültigkeitsbereich einer Variablen; §1.5, §1.8.

Halten Sie die Gültigkeitsbereiche klein; §1.5; [CG: ES.5].

Vermeiden Sie »magische Konstanten«, verwenden Sie symbolische Konstanten; §1.6; [CG: ES.45].

Bevorzugen Sie unveränderliche Daten; §1.6; [CG: P.10].

Deklarieren Sie (nur) einen Namen pro Deklaration; [CG: ES.10].

Halten Sie häufig benutzte und lokale Namen (Bezeichner) kurz; halten Sie selten benutzte und nichtlokale Namen länger; [CG: ES.7].

Vermeiden Sie ähnlich aussehende Namen; [CG: ES.8].

Vermeiden Sie ALL_CAPS-Namen; [CG: ES.9].

Benutzen Sie auto, um sich wiederholende Typnamen zu vermeiden; §1.4.2; [CG: ES.11].

Vermeiden Sie nichtinitialisierte Variablen; §1.4; [CG: ES.20].

Deklarieren Sie eine Variable erst, wenn Sie einen Wert haben, mit dem Sie sie initialisieren können; §1.7, §1.8; [CG: ES.21].

Wenn Sie eine Variable in der Bedingung einer if-Anweisung deklarieren, dann bevorzugen Sie die Version mit dem impliziten Prüfen gegen 0 oder nullptr; §1.8.

Bevorzugen Sie bereichsbasierte for-Schleifen gegenüber for-Schleifen mit einer expliziten Schleifenvariablen; §1.7.

Benutzen Sie unsigned nur für Bit-Manipulationen; §1.4; [CG: ES.101][CG: ES.106].

Halten Sie die Verwendung von Zeigern einfach und unkompliziert; §1.7; [CG: ES.42].

Benutzen Sie nullptr statt 0 oder NULL; §1.7; [CG: ES.47].

Sagen Sie in Kommentaren nichts, was ganz klar in Code ausgedrückt werden kann; [CG: NL.1].

Drücken Sie in Kommentaren Ihre Absichten aus; [CG: NL.2].

Wahren Sie einen konsistenten Stil bei Ihren Einrückungen; [CG: NL.4].

[1] https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md

Kapitel 2: Benutzerdefinierte Typen

Keine Panik!— Douglas Adams

2.1  Einführung

Wir bezeichnen die Typen, die aus den grundlegenden Typen (§1.4), dem const-Modifikator (§1.6) und den Deklaratoroperatoren (§1.7) erstellt werden können, als ‌‌integrierte Typen. Die Menge der in C++ integrierten Typen und Operationen ist sehr umfassend, bewegt sich aber bewusst auf einem niedrigen Level. Sie spiegeln direkt und effizient die Fähigkeiten der herkömmlichen Computerhardware wider. Allerdings bieten sie den Programmiererinnen und Programmierern keine leistungsfähige Unterstützung, um bequem fortschrittliche und moderne Anwendungen zu schreiben. Stattdessen erweitert C++ die integrierten Typen und Operationen um einen ausgefeilten Satz von ‌‌Abstraktionsmechanismen, aus denen Programmiererinnen und Programmierer solche modernen Instrumente aufbauen können.

Die C++-Abstraktionsmechanismen sind vor allem dazu gedacht, den Entwurf und die Implementierung eigener Typen mit passenden Repräsentationen und Operationen und den eleganten und einfachen Einsatz dieser Typen zu erlauben. Typen, die mithilfe der C++-Abstraktionsmechanismen aus anderen Typen gebaut werden, nennt man ‌‌benutzerdefinierte Typen. Sie werden als ‌Klassen und ‌Aufzählungen (Enumerationen) bezeichnet. Benutzerdefinierte Typen können sowohl aus integrierten als auch aus anderen benutzerdefinierten Typen zusammengestellt werden. Der größte Teil dieses Buches ist dem Entwurf, der Implementierung und der Verwendung benutzerdefinierter Typen gewidmet. Benutzerdefinierte Typen werden oft gegenüber integrierten Typen bevorzugt, weil sie einfacher einzusetzen, weniger fehleranfällig und bei dem, was sie machen, meist ebenso effizient, wenn nicht gar effizienter sind als die integrierten Typen.

In diesem Kapitel lernen Sie die einfachsten und grundlegendsten Möglichkeiten zum Definieren und Benutzen von Typen kennen. Die Kapitel 4 bis Kapitel 8 enthalten eine vollständigere Beschreibung der Abstraktionsmechanismen und der Programmierstile, die von ihnen unterstützt werden. Benutzerdefinierte Typen sind das Rückgrat der Standardbibliothek, weshalb die entsprechenden Kapitel zur Standardbibliothek, nämlich die Kapitel 9 bis Kapitel 17, Beispiele dafür bieten, was mithilfe der Sprachmöglichkeiten und Programmiertechniken umgesetzt werden kann, die in Kapitel 1 bis Kapitel 8 vorgestellt werden.

2.2  Strukturen

Der erste Schritt beim Erstellen eines neuen Typs besteht oft darin, die Elemente, die dieser benötigt, in einer Datenstruktur, einem ‌struct, zu organisieren:

struct Vector { double* elem; // Zeiger auf Elemente int sz; // Anzahl der Elemente};

Diese erste Version von Vector besteht aus einem int und einem double*.

Eine Variable des Typs Vector kann so definiert werden:

Vector v;

Für sich allein genommen nützt das jedoch nicht viel, da der elem-Zeiger von v