GoingNative 2012 – Gegenwart und Zukunft von C++

Sprachen  –  23 Kommentare

Für die erstmalig ausgetragene Konferenz GoingNative 2012, die ganz im Zeichen des neuen C++11-Standards stand, versammelte Veranstalter Microsoft auf seinem Campus eine illustre Schar von C++-Größen, um über den Status quo von C++11 zu diskutieren. Dem Ruf nach Seattle waren unter anderem Bjarne Stroustrup, Andrei Alexandrescu und Herb Sutter gefolgt,

Den Auftakt machte Bjarne Stroustrup, seines Zeichens Erfinder der Sprache, mit seiner Keynote über "C++ Style", in der er seine Schöpfung zunächst zu charakterisieren suchte: C++ sei eine "leichtgewichtige Abstraktionssprache", deren Einsatzmöglichkeiten er explizit nicht in Anwendungsfeldern sieht, bei denen es auf schnelle Markteinführung ankomme. Vielmehr spiele C++ seine Stärken dort aus, wo Softwarefehler Todesfälle nach sich zögen ("if something fails, people die").

C++-Entwickler möchten laut Stroustrup Nebenläufigkeit, effiziente Ressourcenverwaltung, Portabilität, Modularität und Quellcode-Verständlichkeit miteinander kombinieren. C++ sei mit der Zeit deutlich besser darin geworden, diese Ziele miteinander zu vereinbaren. Es sei aber wichtig, jetzt zu kommunizieren, wie Entwickler C++11 richtig einsetzen könnten – ein langfristiger Prozess, wenn auch alle wichtigen Compiler bereits signifikante Teile des neuen Standards unterstützten. Stroustrup verwies hierzu auf seinen Artikel "Software Development for Infrastructure" (PDF).

Im Rest der Keynote ging Stroustrup auf einige der darin angesprochenen Stilaspekte ein: "High-Level- statt Low-Level-APIs", "Type-rich Interfaces", "Ressourcen, RAII-Idiom (Resource Acquisition Is Initialization), Move-Semantik" und "kompakte Daten".

Als Beispiel dafür, dass "low level" nicht gleich "effizient" sei, nannte er die C-Standardfunktion qsort(), seiner Meinung nach ein Beispiel für eine "70er-Jahre-Funktion", die von der C++-Funktion std::sort() auf seinem System um den Faktor 2,5 überboten würde. Der Programmierer solle in Algorithmen denken und nicht in Schleifen und Verzweigungen.

In der abendlichen Podiumsdiskussion brachte Herb Sutter es folgendermaßen auf den Punkt: APIs sollten die Absicht des Programmierers einfangen; Bibliothek und Compiler dann dieses Ziel optimal umsetzen. Stroustrup verglich dazu den seriell gedachten find_if-Algorithmus mit einem parallelisierungsfreundlichen fiktiven find_all-Algorithmus (Sutter: find_any).

Stroustrups nächster Rat befasste sich mit Type-rich Interfaces. Darunter versteht er die Fokussierung auf Schnittstellen mit aussagekräftigen Typen. Ein besonders berüchtigtes Beispiel für das, was Stroustrup "semantikfreie Schnittstellen" nennt, sei eine Funktion wie void increase_speed(double). Ein double sage nichts über die Einheit der Geschwindigkeit aus. Genau dieses Problem habe zum Verlust des Mars Climate Orbiter geführt und damit immerhin ein 500-Millionen-Dollar-Investment und die kombinierte Lebensarbeitszeit von 200 Ingenieuren vernichtet.

C++11 biete hierfür benutzerdefinierte Literale an, mit denen Entwickler formulieren könnten:

  Speed speed = 100m/9.8s;
increase_speed( speed );

Das stelle eine Berechnung rein zur Compile-Zeit dar, ohne jeglichen Laufzeit-Overhead, und sei daher auch in so ressourcenbeschränkten Systemen wie Raumfahrzeugen einsetzbar.

Neben Orientierungshilfen für den Einsatz von RAII und Move-Semantik, in denen er für den Verzicht auf Zeigervariablen (auch shared_ptr) plädierte, befasste sich die Präsentation zuletzt auch mit "kompakten Daten": Anhand eines Benchmarks zwischen vector und list verdeutlichte er die Bedeutung des Layouts von Datenstrukturen. Prägnant formulierte er: "list optimiert Cache Misses".

Das sei, so Alexandrescu später, ein Problem der High-Level- (Stroustrup: der wahren objektorientierten) Sprachen, in denen alles eine Referenz sei: Der Compiler müsse aufwendig die durch die Referenzen erzeugten Indirektionen wieder wegoptimieren.

Eine Frage aus dem Publikum drehte sich um den von Stroustrup verfassten JSF-Coding-Standard (PDF), der unter anderem verbiete, Ausnahmen zu werfen. Es passe nicht recht zu seiner Präsentation, wenn Projekte im Bereich der eingebetteten Systeme per Coding-Standard C++-Features verbieten müssten. Stroustrup löste den Widerspruch auf, indem er darauf hinwies, dass sich der zitierte Coding-Standard auf harte Echtzeitsysteme beziehe, in denen es besonders auf Vorhersagbarkeit ankäme. In C++ gäbe es aber einige wenige Konstrukte (new/delete, dynamic_cast und eben Ausnahmen), deren Laufzeiten nicht vorhersagbar und die daher in Echtzeitsystemen auszuschließen seien.

Später präzisierte er in der Podiumsdiskussion: Was für ein gegebenes Projekt wie JSF sinnvoll sei, könne dennoch zur Zersplitterung der C++-Gemeinde führen, weshalb das ISO-Komitee solchen C++-Untermengen nicht offiziell seinen Segen geben werde.

"Threads and Shared Variables in C++11"

Hans J. Boehm sprach über Multithreading in C++11. Neben der Definition von APIs für die Arbeit mit Threads (std::thread, std::async(), std::future, std::mutex), was im Wesentlichen durch Boost.Threads geschehen sei, sei es auch notwendig, ein Speichermodell zu entwerfen, das insbesondere vorschreibt, wie von Threads gemeinsam genutzte Variablen zu verwenden seien.

Das von Java und C++11 verwendete Modell sei "SC for DRF ("sequenzielle Konsistenz für wettlauffreie Programme"/"sequential consistency for data-race-free programs"). Unter sequenzieller Konsistenz versteht Boehm das klassische Modell der verschachtelten Ausführung: In jedem Schritt wird der nächste Befehl eines wahlfreien Threads ausgeführt. Der Programmierer muss alle erlaubten Verschachtelungen analysieren, um die Korrektheit des Programms zu verifizieren, was nicht nur extrem aufwendig sei, sondern, so Boehm weiter, auch nicht mehr dem Modell entspräche, das heutige CPUs implementierten. Er präsentierte hierzu "Dekkers Beispiel":

  // Thread 1         // Thread 2
x = 1; y = 1;
r1 = y; r2 = x;

Im klassischen SC-Modell könnten niemals r1 = r2 = 0 sein, denn jede mögliche Ausführung beginne entweder mit x = 1 oder mit y = 1. Reale Hardware zeige r1 = r2 =0 jedoch regelmäßig, ausgelöst durch vorgezogene Lade- und verzögerte Speicherbefehle in Compiler und Hardware.

Der Vorteil des SC-for-DRF-Modells bestehe darin, dass Entwickler kritische Wettläufe anhand des vertrauten SC-Modells aufdecken, bei gezeigter Wettlauffreiheit aber den Code so betrachten könnten, als würden Quellcodeblöcke zwischen Synchronisationspunkten atomar ausgeführt.

"STL Magic && Secrets"

Stephan T. Lavavej, Hauptentwickler von Microsofts STL-Implementierung (Standard Template Library), sprach über einige Tricks, die er in der Implementierung der STL verwendet habe.

Durch Vereinigen von Zählervariable und Nutzlast eines shared_ptr in einer einzigen Speicheranforderung könne zum Beispiel make_shared deutlich effizientere shared_ptr-Instanzen erzeugen. Für den C++11-Entwickler heißt das: Wo immer möglich, sollte er make_shared anstelle des klassischen shared_ptr(T*)-Konstruktors verwenden.

Ein ähnliches Beispiel sei die emplace()-Funktion, die viele STL-Container anbieten. Hierdurch ließe sich nicht nur der Copy-, sondern darüber hinaus auch der Move-Konstruktor einsparen, da das neue Element direkt in den Container konstruiert werde.

Ganz besonders lag Lavavej std::pair am Herzen, an dessen Beispiel er einige "haarige Abgründe" des neuen C++-Standards erläuterte, bevor er gegen Ende bekannt gab, dass VC++11 doch "range-based for loops" unterstützen werde.

"Variadic Templates are Funadic"

Andrei Alexandrescu, Autor eines wegweisenden Buchs [1] über Richtlinien-basiertes Design (policy-based design) und seit der Zeit als Template-Guru angesehen, gab eine Einführung in variadische Templates, also Templates mit einer variablen Anzahl von Argumenten (ähnlich printf() für C). In einem vergnüglichen und mit Selbstironie gespickten Vortrag ging er neben Syntax und Semantik variadischer Templates auch auf konkrete Implementierungen von tuple und einer fiktiven safe_printf()-Funktion ein.

Befürchtungen des Publikums hinsichtlich der aus Alexandrescus und Lavavejs Vorträgen sprechenden Komplexität von C++ ("Sind variadische Templates nur etwas für große Firmen?") entgegnete Sutter in der nachfolgenden Podiumsdiskussion: Es gäbe die Tendenz, in Vorträgen die besonders komplizierten Sachverhalte in den Vordergrund zu stellen. Solche Vorträge sollten als "nicht für die Arbeit geeignet" ("not safe for work") markiert werden. Man könne die Inhalte ignorieren und trotzdem in C++ produktiv sein. Stroustrup fügte hinzu: Eine Bibliothek zu benutzen sei "sehr, sehr viel einfacher", als sie zu schreiben. Sutter: "Diese Leute schreiben Code, den Sie nie zu Gesicht bekommen". Stroustrup: "Außer in Fehlermeldungen".