Neues vom C++ Programmierer Liebe Leserinnen, liebe Leser,

nunmehr ist die dritte Auflage meines Buchs »Der C++ Programmierer« erschienen. Es richtet sich an alle, die einen Einstieg in C++ suchen. Beim ersten Lesen können tiefer gehende Kapitel, die entsprechend gekennzeichnet sind, übersprungen werden. Erfahrung mit einer Programmiersprache wird nicht vorausgesetzt.

Die dritte Auflage unterscheidet sich von der vorherigen durch die vollständige Umstellung auf den 2011 verabschiedeten ISO C++-Standard, C++11 genannt, sowie durch Fehlerkorrekturen und kleinere Verbesserungen. Dabei gibt es keinen extra Abschnitt zu den Neuerungen des Standards, wie in manchen anderen Büchern. Die Neuerungen wurden vielmehr integriert, um ein Buch aus einem Guss anzubieten, zumal aktuelle Compiler C++11 unterstützen. Außerdem wird jetzt schon die nächste Überarbeitung des Standards mit dem Arbeitsnamen C++14 diskutiert. Dabei geht es jedoch nur um kleinere Verbesserungen und Fehlerbeseitigungen. Die Zahl 14 deutet auf den beabsichtigten Veröffentlichungstermin noch 2014 hin. Tatsächliche Veröffentlichungen ehemaliger Standardversionen lagen jedoch Jahre nach dem jeweiligen Wunschtermin. Das ist hier auch zu erwarten. Eine Auswahl der Neuerungen des C++11-Standards finden Sie unten.

Die vielen Beispiele sind leicht nachzuvollziehen. Klassen und Objekte, Templates, STL und Exceptions sind bald keine Fremdwörter mehr für Sie. Softwareentwicklung ist nicht nur Programmierung. Deshalb wird Wert auf eine saubere Programmiermethodik gelegt, um qualitativ hochwertige und fehlerarme Software bauen zu können. Dem entsprechend gibt es zahlreiche Tipps zum Entwurf von Programmen. Im Download-Bereich der Website zum Buch finden Sie alle Beispiele und Lösungen zusammen mit Werkzeugen zur Programmentwicklung zum Herunterladen.

Das integrierte »C++-Rezeptbuch« enthält nicht nur diese Tipps, sondern auch etliche Lösungen zu praktischen Problemstellungen. Das sehr umfangreiche Register und ein detailliertes Inhaltsverzeichnis helfen bei der Suche nach einer Lösung.

Fortgeschrittene finden in diesem Buch auch kurze Einführungen zu Themen wie Thread- und Netzwerkprogrammierung und grafische Benutzungsoberflächen. Durch den Einsatz der Boost- und Qt-Libraries wird größtmögliche Portabilität erreicht.

Das Buch eignet sich nicht nur zum Selbststudium, sondern auch als Begleitbuch zu einer Vorlesung. An vielen Hochschulen und Universitäten haben Studierende die Möglichkeit, kostenlos auf eine elektronische Version des Buchs zugreifen zu können, weil die Hochschulbibliotheken eine entsprechende Lizenz vom Verlag erworben haben.

Auswahl einiger Neuerungen des C++11-Standards

Auf alle neuen Spracheigenschaften einzugehen fehlt hier der Raum, deswegen wird eine Auswahl getroffen. Ob eine Neuerung die Qualität von Programmcode aus softwaretechnischer Sicht erhöht, ist dabei ein Kriterium. Dazu gehören etwa Maßnahmen zur Erhöhung der Typsicherheit, um mögliche Fehler bereits zur Compilationszeit erkennen zu können, wie auch Maßnahmen zur Vereinfachung der Programmierung. Ein weiteres Kriterium kann die Verbesserung der Performance sein. Hier werden die Neuerungen nur kurz angerissen; im Buch finden Sie ausführliche Erklärungen und Beispiele dazu.

Das Buch richtet sich auch an Neueinsteiger. Die nachfolgend angesprochenen Neuerungen sind jedoch nur für Menschen mit Vorkenntnissen verständlich, ob mit Hilfe des Buchs oder anderweitig erworben.

Im alten C++ waren die doppelten spitzen Klammern >>, etwa in der Deklaration

vector<vector<int>> vvi;

oft ein Ärgernis, weil sie vom Compiler als Shift-Operator interpretiert wurden und er somit eine Fehlermeldung ausgab. Es fehlte ein Leerzeichen dazwischen. C++11 versteht, dass es sich um geschachtelte Templates handelt.

constexpr ist ein neues Schlüsselwort, das anzeigt, dass ein konstanter Ausdruck bereits zur Compilierzeit berechnet werden kann. Es ersetzt nicht const: Zum Beispiel kann ein const-Wert in einer Funktion von einem übergebenen Parameter, der erst zur Laufzeit bekannt ist, abhängen.

auto kennzeichnete in vergangenen Zeiten Variable, die auf dem Laufzeitstack abgelegt wurden (lokale „automatische“ Variable). In C++11 hilft es, den Typ eines Ausdrucks automatisch zu bestimmen, etwa

auto wert = function();

Der Vorteil besteht nicht nur in der Arbeitserleichterung beim Schreiben des Programms, weil man sich nicht um den Typ kümmern muss, sondern auch in der verbesserten Wartbarkeit des Programms bei Typänderungen.

Eine for-Schleife mit Bereichsangabe (engl. range-for statement) ist eine kurze Variante einer for-Schleife über alle Werte eines Containers (Vektor, Liste, …). Statt etwa

for(size_t i = 0; i < container.size(); ++i) {
   cout << container[i] << '\n';
}

kann nun geschrieben werden:

for(auto wert : container) {
   cout << wert << '\n';
}

Der Vorteil besteht in der einfacheren Schreibweise und damit der Vermeidung von Schreibfehlern wie „<=“ statt „<„. Mit der neuen Schreibweise ist eine Überschreitung des gültigen Bereichs (Indexfehler) ausgeschlossen.

nullptr ist ein Schlüsselwort, das einen Zeiger auf „nichts“ (Null-Zeiger) bezeichnet. Im vorhergehenden C++-Standard wurde die Zahl 0 dazu benutzt; dies konnte jedoch zu Typproblemen führen. So ist nicht klar, ob ein Aufruf f(0) zur Funktion f(int) gehört oder zur überladenen Funktion f(void*). f(nullptr) gehört eindeutig zur zweiten genannten Funktion.

static_assert prüft bereits zur Compilationszeit, ob eine Bedingung gültig ist. Zum Beispiel kann es im Einzelfall notwendig sein, dass der Typ long mehr Bits als der Typ int haben muss, wenn das Programm korrekt funktionieren soll. In manchen Systemen haben sowohl int wie auch long die Bitbreite 32. Die Anweisung

static_assert(sizeof(long) > sizeof(int), "long hat nicht mehr Bits als int!");

prüft das schon zur Compilationszeit, sodass sich ein Test zur Laufzeit mit assert() erübrigt.

long long ist ein Typ, der die mögliche Beschränkung von manchen long-Implementationen auf 32 Bit aufhebt, weil er mindestens 64 Bit hat. Damit ist C++ konform zum aktuellen C-Standard.

Bisher wurden Objekten und Arrays auf verschiedene Arten initialisiert. Zur Vereinfachung bietet C++11 eine einheitliche Syntax für die Initialisierung mit Hilfe der geschweiften Klammern an. In diesem Zusammenhang ist die Klasse initializer_list eingeführt worden, mit deren Hilfe die in den geschweiften Klammern angegebenen Elemente abgearbeitet werden. Die Anweisung

vector vs {"gute", "Idee"};

initialisiert den Vektor mit zwei Strings. Dabei wird der Konstruktor vector(initializer_list) aufgerufen. Die Klasse initializer_list kann auch in eigenen Klassen benutzt werden, wie im Buch gezeigt wird.

Für Enumerationen (Aufzählungen) ist das Schlüsselwort enum zuständig. Dabei ist die Typumwandlung eines Werts nach int möglich. Im Sinne einer besseren Typsicherheit gibt es nun die Möglichkeit, enum class zu schreiben. Mit diesem Typ ist eine versehentliche Typumwandlung nach int nicht mehr möglich. Wenn doch eine Typumwandlung beabsichtigt ist, muss man static_cast bemühen.

Lambda-Funktionen oder -Ausdrücke sind anonyme (unbenannte) Funktionen, die direkt an der Stelle ihrer Verwendung definiert werden. Die Funktionen haben ihren Namen vom sogenannten Lambda-Kalkül, einem formalen System zur Erforschung einiger theoretischer Grundlagen der Mathematik und Informatik. Lambda-Funktionen werden wie ein Funktionsobjekt benutzt, nur dass man sich das Schreiben einer Klasse und der zugehörigen Funktion operator()() sparen kann. Sie sind immer dann sinnvoll, wenn eine Funktion nur ein einziges Mal aufgerufen werden soll. Im Beispiel werden die Elemente des Vektors v nach dem Absolutbetrag sortiert:

sort(v.begin(), v.end(), [](int x, int y) { return abs(x) < abs(y);});

Die Kennzeichnung der Funktion einer Klasse mit override erlaubt es dem Compiler, eine Warnung bei Schreibfehlern auszugeben (das zweite ‚virtual‚ darf entfallen):

class Basis {
   virtual void func();
};

class Abgeleitet {
   virtual void Func() override; // versehentlich großgeschrieben: 
                                 // Fehlermeldung!
};

Die Kennzeichnung der Funktion einer Klasse mit final verhindert das Überschreiben in einer abgeleiteten Klasse:

class Basis {
   virtual void func() final;
};

class Abgeleitet {
   virtual void func(); // Fehler! func() darf nicht überschrieben werden.
};

Variadic Templates sind Templates mit einer variablen Anzahl von Template-Parametern. Sie werden unter anderem in der Bibliotheksklasse tuple (Tupel) verwendet. Ein Tupel-Objekt speichert eine feste, zur Compilationszeit festgelegte Anzahl von Elementen auch unterschiedlichen Typs. Wegen der Variadic Templates muss die Anzahl der Elemente in der Deklaraition von tuple jedoch nicht bekannt sein. Im Buch werden Variadic Templates beispielhaft bei der Auswertung von Matrix-Rechenoperationen benutzt.

C++ basiert auf der Wertsemantik. C++11 stellt zusätzlich die Move-Semantik einschließlich unterstützender Datentypen und Funktionen zur Verfügung. Im Buch wird gezeigt, dass damit Programme bei bestimmten Problemstellungen erheblich schneller gemacht werden können.

Breymann, Der C++ Programmierer, 3.A.

Breymann, Der C++ Programmierer, 3.A.

Soweit zu einigen Neuerungen des C++11-Standards. Weitere Informationen zur C++ Programmierung finden Sie in der soeben erschienenen dritten aktualisierten und vollständig überarbeiteten Auflage Der C++ Programmierer des Autors.