Effektives modernes C++

C++ wird gerne als der Dinosaurier unter den Programmiersprachen bezeichnet. Denn die Sprache ist bereits über 30 Jahre alt; die erste Veröffentlichung durch den Erfinder Bjarne Stroustrup datiert auf 1983, erste Veröffentlichen zu “C with Classes” gab es sogar bereits 1979. Die Bezeichnung als Dinosaurier bezieht sich aber auch auf den Umfang. Startete C++ noch (weitgehend) als Erweiterung zu C, wurden die Sprachfeatures durch die Erweiterungen in den folgenden Jahren immer umfangreicher. Der Einarbeitungsaufwand in C++ gilt heute als sehr hoch.

Zu seinem Baby veröffentliche Bjarne Stroustrup neben weiteren Büchern das Standardwerk Die C++ Programmiersprache, das heute in der vierten Auflage vorliegt. Es bildet eine Einführung in die Sprache und enthält eine umfangreiche Referenz zum Sprachstandard und der Standardbibliothek. Viele Entwickler vermissten aber eine Hilfestellung, wie man sich die Denkweise hinter C++ aneignet und für eigene Projekte vorteilhaft einsetzt.

In diese Lücke sprang 1992 der Autor Scott Meyers mit seinem Werk Effektiv C++ programmieren. Es enthielt 55 Programmiertechniken, die sich die Vorzüge der Objektorientierung im Allgemeinen und von C++ im Speziellen zu Nutze machten, um damit effiziente, lesbare und wartbare Software zu entwickeln.

Effektives modernes C++ ist der numher vierte Band der Effektiv C++ Reihe. Er erschien 2014 und liegt seit kurzem auch in der deutschen Übersetzung vor. Auf 293 Textseiten behandelt er Programmiertechniken auf Basis der Neuerungen in den Standards C11 und C14 von 2011 bzw. 2014. Die Nutzung dieser Möglichkeiten wird zu Recht als Modernes C++ bezeichnet, denn C++ schließt dadurch in den Möglichkeiten und der Ausdrucksstärke zu wesentlich jüngeren Sprachen auf.

Das Buch behandelt nach einem Einführungskapitel 42 Programmiertechniken, die in acht Kapiteln zu Themengebieten zusammengefasst sind. Jedes Kapitel kann unabhängig von den anderen gelesen werden. Innerhalb der Themengebiete bauen die Programmiertechniken lose aufeinander auf. Wo Zusammenhänge zu anderen Themen oder Techniken bestehen, wird das durch Querverweise deutlich gemacht. Jedes Kapitel behandelt ein Spracheigenschaft, die mit C++11 oder C++14 neu zum Standard-C++ hinzugekommen ist. Eine Ausnahme bildet Kapitel 3, wo es um die Migration von älterem C++-Code zu C11 geht. Hier spielen verschiedene Aspekte von modernem C++ eine Rolle, die zu klein für ein eigenes Kapitel sind.

Beim Lesen fällt auf, dass Scott Meyers konsequent aus der Sicht des Anwenders schreibt, der C++ für eigene Entwicklungsprojekte einsetzt. Obwohl Meyers auch aktiv in den Standardisierungsprozess von C++11 und C++14 involviert war, spart er nicht an einer eigenen Bewertung des Resultats und drückt seine Kritik in mitunter sehr trockenem Humor aus.

Die einzelnen Techniken sind weitgehend orthogonal aufgebaut. Es wird zunächst eine Problemstellung beschrieben und teilweise eine Lösung ohne Verwendung der jeweiligen Technik angegeben. Dabei werden einfache Sourcecode-Listings verwendet, die man mit wenig Aufwand auch direkt ausprobieren kann. Anschließend werden die Nachteile der Lösung beschrieben und das Beispiel in z.T. mehreren Schritten verfeinert, bis eine optimale Lösung gefunden wird. In den Beispielen wird dabei immer in Fettdruck hervorgehoben, was sich geändert hat oder worauf der Leser besonders achten soll. Wo nötig, werden alte Codebeispiele nochmal wiederholt und neuen direkt gegenübergestellt.

Von dem Umfang von 293 Textseiten darf man sich nicht täuschen lassen. Scott Meyers packt auf eine Buchseite so viel Information wie kaum ein anderer Computerbuch-Autor. Durch seinen präzisen, schnörkellosen und dennoch humorvollen Schreibstil wird jede Programmiertechnik eingehend beschrieben. Wer das Buch von vorne bis hinten durcharbeitet, ist länger beschäftigt, als es zunächst den Anschein erweckt.

O’Reilly bietet auf der deutschen Homepage das erste Kapitel Typen ableiten als PDF-Datei zum Probelesen an. Wem der Stil der ersten vier Techniken gefällt, kann das Buch bedenkenlos kaufen, denn die weiteren Techniken sind weitgehend orthogonal aufgebaut. Von der englischsprachigen Originalversion gibt es (nach einer Registrierung) neben den ersten vier Techniken noch die Techniken 7, 14 und 41 als Leseprobe.

Ein Lob verdient auch die deutsche Übersetzung an sich. Anders als bei vielen anderen Computerbüchern ist die Übersetzung sprachlich gut gelungen, das Buch flüssig zu lesen. Echte Übersetzungsfehler oder Mehrdeutigkeiten habe ich nicht gefunden. Lediglich an einigen wenigen Stellen scheinen Anglizismen durch, wenn Formulierungen zu wörtlich übersetzt werden. Zum Beispiel hört sich “Während des Kompilierens” nach einer Übersetzung von during an; mangels zeitlichen Bezuges klänge aber “Beim Kompilieren” im Deutschen eigentlich schöner.

Insgesamt ist Effektives modernes C++ ein sehr wichtiges Buch für C++ Programmierer. Es ersetzt weder ein Lehrbuch für Einsteiger noch ein Nachschlagewerk für die Sprache und die Libraries. Solide Kenntnisse in C++ und zumindest ein rudimentärer Überblick über C++11 und neuer werden vorausgesetzt. Das Buch gibt dem Programmierer aber eine wertvolle Hilfe bei der Umsetzung der neuen Möglichkeiten der aktuellen C++ Standards und hilft unmittelbar, besseren, fehlerärmeren und verständlichen Code zu programmieren. Anders als der erste Band der Reihe ist das Buch wirklich ausschließlich für C++1114 relevant; die Techniken und Beispiele sind zu speziell, um für andere Programmiersprachen nützlich zu sein.

Die acht Kapitel behandeln die folgenden Themenbereiche.

Typen ableiten

Im ersten Kapitel geht es um die Regeln zur automatischen Typableitung. Diese gab es bereits in älteren C++-Standards, durch die Hinzunahme von automatischem Typing wurden jedoch die Regeln stark erweitert. In drei Techniken werden die Regeln und ihre Sonderfälle bei Funktionstemplates, auto, decltype und dem mit C++14 hinzugekommen decltype(auto) besprochen. Die vierte Technik behandelt die Möglichkeiten, den Typ eines Ausdrucks zu bestimmen, mit IDEs, Compilern und zur Laufzeit.

auto

Das zweite Kapitel behandelt die Vor- und Nachteile Verwendung der automatischen Typableitung. Im Allgemeinen sollte diese verwendet werden, weil das die Lesbarkeit und Wartbarkeit seiner Codebasis zu Gute kommt. Scott Meyers beschreibt jedoch verschiedene Ausnahmefälle, in denen auto nicht das erwartete Ergebnis hat und besser vermieden werden sollte.

Der Wechsel zu modernem C++

Dieses Kapitel bildet eine lose Zusammenstellung von Vorteilen von C++11 und C++14 gegenüber älteren Standards und Tipps für die Umstellung der eigenen Codebasis. Die einzelnen Techniken bauen weitgehend nicht aufeinander auf. Behandelt werden u. A. nullptr, Funktionsüberschreibung per override, const_iterator und die Thread-Sicherheit von const-Memberfunktionen.

Smart Pointer

Mit der Einführung von C++11 gibt es eine verwirrende Vielfalt an Möglichkeiten, Pointer zu speichern. Neben den aus C bekannten Pointern, wie sie mit new() erzeugt werden, führte C++ auto_ptr ein. Mittlerweile gibt es noch unique_ptr, weak_ptr und shared_ptr, die Scott Meyers zusammenfassend als Smart Pointer zusammenfasst. In den hier beschriebenen Techniken wird erklärt, für welche Anwendungsbereiche die jeweiligen Typen gedacht sind, wie man sie ineinander konvertiert und welche Probleme zu erwarten sind, wenn man den falschen Typ wählt.

Move-Semantik

Die Move-Semantik ist wahrscheinlich die wichtigste Neuerung von C++. Sie ersetzt das bisherige Paradigma der Copy Semantik bei der Übergabe von Funktionsparamatern um eines, bei dem keine tiefe Kopie des übergebenen Objektes erstellt und somit Speicherplatz und Laufzeit gespart wird. Die Besonderheit ist, dass man in bestehenden Programmen lediglich die Definition eines Konstruktors oder Zuweisungsoperators ändern muss, um die Klasse vollständig auf Move-Semantik umzustellen. Wie das geht, wo das sinnvoll ist und welche “Optimierungen” man besser vermeidet, zeigen die acht Techniken dieses Kapitels.

Lambda-Ausdrücke

Mit der Einführung von Lambda-Ausdrücken rückt die imperative und objektorientierte Programmiersprache C++ ein Stück weit in Richtung der funktionalen Sprachen. Das die Einführung dieses Features in eine featurereiche Sprache, die insgesamt weit weg von funktionaler Programmierung steht, nicht ganz schmerzlos ist und wie man sie dennoch elegant verwendet, zeigt Scott Meyers in diesem Kapitel.

Concurrency

Die zweite wichtige Neuerung von modernem C++ nach der Move-Semantik ist wahrscheinlich die Concurrency-API. Modelle und APIs zur nebenläufigen Programmierung gab es bereits mehrere, neu ist aber, das eines den Einzug in Standard-C++ geschafft hat und vermutlich langfristig die anderen verdrängen wird. Die nebenläufige Programmierung in C++ ist ein umfangreiches Thema, mit dem man leicht ein ganzes Buch füllen könnte. Scott Meyers beschränkt sich auf einige Hinweise, welche Funktionen der API für welche Anwendungsszenarien geeignet sind beleuchtet potenzielle Probleme beim Beenden von Threads.

Wertübergabe und Emplacement

Im letzten Kapitel werden zwei spezielle Fälle bei der Wertübergabe an Methoden behandelt. Diese sind lose mit der Move-Semantik verwandt, könnten also durchaus auch im fünften oder in dem allgemein gehaltenen dritten Kapitel behandelt werden. Anders als in den genannten Kapiteln geht es hier aber weniger um Effektiviät, sondern um Effizienz. Die hier gegebenen Tipps könnte man durchaus als obskur bezeichnen, sie führen aber zu einer Optimierung der Performance. Daher hat der Autor ihnen vermutlich ein eigenes Kapitel spendiert.

Scott Meyers, Effektives modernes C++, O’Reilly Verlag 2015, ISBN 978-3-95875-049-4

Ich bedanke mich beim Verlag O’Reilly, der über den Linux Workshop Köln das Rezensionsexemplar bereit gestellt hat.