In den vergangenen Jahren war immer wieder von der „C++-Renaissance“ die Rede. Man muss anerkennen, dass Microsoft einen wesentlichen Anteil an dieser Bewegung hatte; ich erinnere mich an dieses Video in dem Craig Symonds und Mohsen Agsen darüber sprachen.
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.
2011 war C++ bereits seit mehr als 30 Jahren im Einsatz. Es war nicht leicht, Entwickler davon zu überzeugen, dass das neue C++ viele frustrierende Aspekte der Sprache tatsächlich vereinfachte und dass es nun einen modernen Ansatz gab, C++-Code zu verbessern.
Nehmen wir die Speicherverwaltung als Beispiel – sie gehört wohl zu den am häufigsten kritisierten Aspekten von C++. Viele Jahre lang wurden Objekte mit dem Schlüsselwort new angelegt, und Entwickler mussten daran denken, an anderer Stelle im Code delete aufzurufen. „Modern C++“ entschärfte dieses Problem, indem die Verwendung von Shared Pointern gefördert wurde.
Als C++0x einige Jahre zuvor angekündigt wurde, dachte ich, es würde die Sprache C++ kaum verändern. Damit lag ich falsch. Werfen Sie einen Blick auf diesen Codeausschnitt aus Folly – er wirkt, als wäre er in einer neuen Sprache geschrieben worden.

Dasselbe gilt für nahezu den gesamten Folly-Quellcode: Seine Implementierung unterscheidet sich deutlich von typischem C++03-Code.
Wie lässt sich der Einfluss der C++-Vergangenheit begrenzen?
Eine Patentlösung gibt es nicht. Wir können hoffen, dass C++-Compiler uns unterstützen, indem sie vor veralteten Praktiken warnen, etwa vor den alten Funktionen zur Zeichenkettenmanipulation (strcpy, strcat, …). Doch das allein wird wenig bewirken. Bei Modern C++ geht es vor allem darum, neue Idiome zu lernen und konsequent anzuwenden.
Eine andere Möglichkeit besteht darin, so zu tun, als wäre eine neue Sprache namens „Modern C++“ entstanden. Führen wir dieselbe Websuche wie zuvor durch, diesmal jedoch nach „Modern C++“ und Objektallokation – schon der erste Treffer wird Smart Pointer behandeln.
Die neue Sprache MC++ entdecken
Eine gute Möglichkeit, die Stärken von MC++ kennenzulernen, besteht darin, den Quellcode eines ausgereiften Projekts zu untersuchen, das diese Features tatsächlich nutzt. Folly von Facebook ist dafür ein sehr gutes Beispiel.
Let's discover some MC++ features used in Folly:
1. auto
C++11 führt mit dem Schlüsselwort auto Typinferenz ein: Der Compiler leitet den Typ einer Variablen bei ihrer Deklaration selbst ab. Folly verwendet auto für nahezu alle Variablendeklarationen; hier ein Beispiel aus dem Quellcode.

Mit auto müssen Sie weniger Informationen ausschreiben, die der Compiler ohnehin bereits kennt.
2. nullptr
Die Konstante 0 erfüllte traditionell eine Doppelrolle: als Ganzzahlkonstante und als Nullzeigerkonstante. C++11 beseitigt diese Mehrdeutigkeit 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 boten sie bereits viele Jahre zuvor an. Die bekannteste Implementierung war boost::shared_ptr. Neu ist ihre Standardisierung – für die Arbeit mit Smart Pointern ist keine externe Bibliothek mehr erforderlich.
Folly setzt die 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 identischem Namen definieren.
C++11 führt enum class ein. Dessen Enumeratoren werden nicht mehr in den umgebenden Scope exportiert. Außerdem kann nun ein zugrunde liegender Typ für ein Enum angegeben werden.

5. static_assert
C++11 bietet mit dem neuen Schlüsselwort static_assert eine Möglichkeit, 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:

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

7. Bereichsbasierte for-Schleifen
C++11 erweitert die for-Anweisung um das „foreach“-Prinzip zum Iterieren über Collections. Dadurch wird der Code einfacher und übersichtlicher. Folly nutzt dieses Feature intensiv; hier ein Beispiel:

8. Initializer-Listen
In C++03 waren Initializer-Listen auf Arrays beschränkt; in C++11 gilt diese Einschränkung nicht mehr. Um eine {}-Liste entgegenzunehmen, verwendet man eine Funktion – häufig einen Konstruktor –, die ein Argument vom Typ std::initializer_list<T>. Hier ein Beispiel für eine Funktion, die std::initializer_list als Argument akzeptiert.

Und so wird sie aufgerufen.

9. noexcept
Wenn eine Funktion keine Exception auslösen kann oder das Programm nicht dafür ausgelegt ist, von dieser Funktion ausgelöste Exceptions zu behandeln, kann die Funktion als noexcept.
Hier ein Beispiel aus dem Folly-Quellcode.

10. move
C++11 führte Rvalue-Referenzen (mit &&) 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 – typischerweise ein temporäres Objekt. Move-Semantik ermöglicht es, Rvalues zu verändern bzw. ihre Ressourcen effizient zu übernehmen.
Dafür führt C++11 zwei neue spezielle Memberfunktionen ein: den Move-Konstruktor und den Move-Zuweisungsoperator.


Hier finden Sie ein gutes Dokument das die Vorteile der Move-Semantik ausführlicher erläutert.
11. Lambda
C++11 ermöglicht die Erstellung anonymer Funktionen, sogenannter Lambda-Funktionen. Weitere Einzelheiten finden Sie hier zu diesem neuen Feature.
Folly verwendet Lambdas in zahlreichen Funktionen; hier ein Beispiel aus dem Quellcode:

12. Explizit als default oder delete deklarierte spezielle Memberfunktionen
In C++03 stellt der Compiler für Klassen, die diese Funktionen nicht selbst definieren, einen Standardkonstruktor, einen Kopierkonstruktor, einen Kopierzuweisungsoperator (operator=) und einen Destruktor bereit. Entwickler können diese Standardimplementierungen durch eigene Versionen ersetzen.
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 lassen sich bestimmte spezielle Memberfunktionen explizit deaktivieren. Der folgende Typ ist beispielsweise nicht kopierbar; dadurch wird der Code einfacher und klarer.

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 der bzw. den Basisklassen prüft, ob eine virtuelle Funktion mit exakt dieser Signatur existiert. Ist das nicht der Fall, meldet der Compiler einen Fehler.
Folly setzt dieses neue Feature umfassend ein:

14. std::thread
Eine Thread-Klasse (std::thread) wird bereitgestellt. Sie erhält ein Funktionsobjekt sowie optional eine Reihe von Argumenten, die an dieses übergeben werden, und führt es in einem neuen Thread aus.
Mit C++11 wird die Arbeit mit Threads einfacher. Hier ist die neue standardisierte Art, einen Thread zu definieren, anhand eines Beispiels aus dem Folly-Quellcode:

15. Ungeordnete Container
Ein ungeordneter Container ist eine Form von Hashtabelle. C++11 stellt vier standardisierte Varianten bereit:
- unordered_map
- unordered_set
- unordered_multimap
- unordered_multiset
Folly verwendet diese neuen Container an vielen Stellen.

Fazit:
Ein Rat für neue C++-Entwickler: Stellen Sie sich vor, C++ hätte seinen Namen geändert, und suchen Sie im Web nach „Modern C++“ statt nur nach C++. Die Ergebnisse unterscheiden sich deutlich – eine Suche ausschließlich nach C++ führt häufig zu älteren Vorgehensweisen.
