Blog 5 Min. Lesezeit

15 wesentliche C++11-Features zur Verbesserung Ihrer C++-Projekte.

Diesen Artikel teilen
15 Essential C++11 Features to Enhance Your C++ Projects.

In den vergangenen Jahren wurde viel über die „Renaissance von C++“ diskutiert. Unbestreitbar ist, dass Microsoft bei diesem Wiederaufleben eine bedeutende Rolle gespielt hat.

2011 kündigte Microsoft in zahlreichen Artikeln das Comeback von C++ an. C++-Experten von Microsoft wie Herb Sutter hielten viele Vorträge darüber, warum C++ zurück sei, und empfahlen dabei vor allem den Einsatz von Modern C++. Gleichzeitig wurde der C++11-Standard verabschiedet, und man begann, von C++ wie von einer neuen Sprache zu sprechen.

Bis 2011 war C++ bereits seit mehr als 30 Jahren im Einsatz. Es war nicht einfach, Entwickler davon zu überzeugen, dass modernes C++ viele frustrierende Aspekte der C++-Entwicklung tatsächlich vereinfachte und einen neuen, modernen Weg bot, C++-Code zu verbessern.

C++-Entwickler, die noch nicht auf C++11 umgestiegen sind, können clang-tidy verwenden, um Vorschläge zur Modernisierung ihrer Codebasis zu erhalten, oder die Modernisierungsfunktion von CppDepend. Im Folgenden stellen wir 15 der am häufigsten verwendeten Features in Open-Source-C++-Bibliotheken vor.

Betrachten wir Folly, das Facebook sechs Jahre zuvor veröffentlicht hatte: Folly ist eine umfangreiche Sammlung wiederverwendbarer C++-Bibliothekskomponenten, die intern bei Facebook intensiv eingesetzt werden. Auf der Website wird die Motivation für die Entwicklung wie folgt beschrieben:

Folly (eine lose Abkürzung für Facebook Open Source Library) ist eine Bibliothek mit C++11-Komponenten, die mit Blick auf Praxistauglichkeit und Effizienz entwickelt wurde. Sie ergänzt – statt mit ihnen zu konkurrieren – Angebote wie Boost und natürlich std. Tatsächlich entwickeln wir nur dann eine eigene Komponente, wenn etwas, das wir benötigen, entweder nicht verfügbar ist oder nicht das erforderliche Performance-Profil erfüllt.

Sehen wir uns 15 C++11-Features anhand des Folly-Quellcodes an:

1. auto

C++11 führt mit dem Schlüsselwort auto die Typinferenz ein. Der Compiler leitet dabei den Typ einer Variablen zum Zeitpunkt ihrer Deklaration ab. Folly verwendet auto für nahezu alle Variablendeklarationen; hier ist ein Beispiel aus dem Quellcode.

c1

Mit dem Schlüsselwort auto müssen Sie weniger Zeit darauf verwenden, Informationen auszuschreiben, die der Compiler bereits kennt.

2. nullptr

Die Konstante 0 erfüllte traditionell eine Doppelrolle als Ganzzahlkonstante und als Nullzeigerkonstante. C++11 behebt dies mit einem eigenen Schlüsselwort für Nullzeiger: nullptr.

Im Folly-Quellcode werden sämtliche Nullzeiger mit dem neuen Schlüsselwort nullptr dargestellt; die Konstante 0 wird dafür nirgends verwendet.

3. shared_ptr

Smart Pointer sind kein neues Konzept; zahlreiche Bibliotheken hatten sie schon viele Jahre zuvor implementiert. Eine der bekanntesten Implementierungen ist boost::shared_ptr. Neu ist ihre Standardisierung – für die Arbeit mit Smart Pointern ist keine externe Bibliothek mehr erforderlich.

Folly setzt den standardisierten Shared Pointer umfassend ein; im Quellcode sind nur noch wenige Raw Pointer vorhanden.

4. Stark typisierte Enums

„Traditionelle“ Enums in C++ bringen ihre Enumeratoren in den umgebenden Gültigkeitsbereich ein. Das kann zu Namenskollisionen führen, wenn zwei unterschiedliche Enums im selben Scope Enumeratoren mit demselben Namen definieren.

C++11 führt das Schlüsselwort enum class ein. Die Enumeratoren werden damit nicht mehr in den umgebenden Scope exportiert. Außerdem lässt sich nun der zugrunde liegende Typ eines Enums festlegen.

c2

5. static_assert

C++11 führt mit dem neuen Schlüsselwort static_assert eine Möglichkeit ein, Zusicherungen bereits zur Compile-Zeit zu prüfen. Das ist besonders nützlich, um Bedingungen für Template-Parameter festzulegen, wie diese Template-Klasse aus dem Folly-Quellcode zeigt:

c3

6. Variadische Templates

Ein variadisches Template kann eine beliebige Anzahl von Template-Argumenten beliebiger Typen aufnehmen. Sowohl Klassen als auch Funktionen können variadisch sein. Folly definiert zahlreiche variadische Templates; hier sind zwei variadische Template-Funktionen aus dem Folly-Quellcode:

c4

7. Bereichsbasierte for-Schleifen

C++11 erweitert die for-Anweisung um das „foreach“-Paradigma zur Iteration über Sammlungen. Dadurch wird der Code einfacher und übersichtlicher. Folly nutzt dieses Feature intensiv; hier ist ein Beispiel.

c6

8. Initialisierungslisten

In C++03 galten Initialisierungslisten nur für Arrays; mit C++11 sind sie nicht mehr darauf beschränkt. Um eine {}-Liste entgegenzunehmen, verwendet man eine Funktion – häufig einen Konstruktor –, die ein Argument vom Typ std::initializer_list<T>. Hier ist ein Beispiel für eine Funktion, die std::initializer_list als Argument akzeptiert.

c7

Und so wird sie aufgerufen.

c8

9. noexcept

Wenn eine Funktion keine Exception auslösen kann oder das Programm nicht darauf ausgelegt ist, von dieser Funktion ausgelöste Exceptions zu behandeln, kann die Funktion als noexcept.

Hier ist ein Beispiel aus dem Folly-Quellcode.

c9

10. move

C++11 führte Rvalue-Referenzen (mit && gekennzeichnet) ein, um eine Referenz auf einen Lvalue von einer Referenz auf einen Rvalue zu unterscheiden. Ein Lvalue ist ein Objekt mit einem Namen, während ein Rvalue kein benanntes Objekt ist, sondern typischerweise ein temporäres Objekt. Move-Semantik ermöglicht es, Rvalues zu verändern bzw. deren Ressourcen effizient zu übernehmen.

Dafür führt C++11 zwei neue spezielle Memberfunktionen ein: den Move-Konstruktor und den Move-Zuweisungsoperator.

c12c10

Hier ist ein guter Artikel der die Vorteile der Move-Semantik ausführlicher erläutert.

11. Lambda

C++11 ermöglicht die Erstellung anonymer Funktionen, sogenannter Lambda-Funktionen.

Folly verwendet sie in zahlreichen Funktionen; hier ist ein Beispiel aus dem Quellcode:

c14

12. Explizit standardisierte und gelöschte spezielle Memberfunktionen

In C++03 stellt der Compiler für Klassen, die diese nicht selbst definieren, einen Standardkonstruktor, einen Kopierkonstruktor, einen Kopierzuweisungsoperator (operator=) und einen Destruktor bereit. Der Entwickler kann diese Standardimplementierungen durch eigene Versionen überschreiben.

Allerdings gibt es nur wenig Kontrolle über die Erzeugung dieser Standardfunktionen. Um eine Klasse beispielsweise grundsätzlich nicht kopierbar zu machen, musste man einen privaten Kopierkonstruktor und Kopierzuweisungsoperator deklarieren, ohne sie zu definieren.

In C++11 können bestimmte Funktionen explizit deaktiviert werden. Der folgende Typ ist beispielsweise nicht kopierbar, wodurch der Code einfacher und klarer wird.

c15

13. override-Bezeichner

In C++03 kann versehentlich eine neue virtuelle Funktion entstehen, obwohl eigentlich eine Funktion der Basisklasse überschrieben werden sollte.

The override spezielle Bezeichner sorgt dafür, dass der Compiler in den Basisklassen prüft, ob eine virtuelle Funktion mit exakt dieser Signatur vorhanden ist. Ist dies nicht der Fall, meldet der Compiler einen Fehler.

Folly nutzt dieses neue Feature intensiv:

c18

14. std::thread

Eine Thread-Klasse (std::thread) wird bereitgestellt. Sie übernimmt ein Funktionsobjekt sowie optional eine Reihe von Argumenten und führt diese in einem neuen Thread aus.

Mit C++11 ist die Arbeit mit Threads einfacher; hier ist die neue standardisierte Methode zum Erzeugen eines Threads, entnommen aus dem Folly-Quellcode:

c20

15. Ungeordnete Container

Ein ungeordneter Container ist eine Form von Hash-Tabelle. C++11 stellt vier standardisierte Varianten bereit:

  • unordered_map
  • unordered_set
  • unordered_multimap
  • unordered_multiset

Folly verwendet diese neuen Container an vielen Stellen.

c21
Diesen Artikel teilen