C++ ist eine von derISO genormteProgrammiersprache. Sie wurde ab 1979 vonBjarne Stroustrup beiAT&T als Erweiterung der ProgrammierspracheC entwickelt. C++ ermöglicht sowohl dieeffiziente und maschinennahe Programmierung als auch eine Programmierung auf hohem Abstraktionsniveau. Der Standard definiert auch eine Standardbibliothek, zu der verschiedene Implementierungen existieren.
Bei der Anwendungsprogrammierung kommt C++ vor allem dort zum Einsatz, wo hohe Anforderungen an die Effizienz gestellt werden, um durch technische Rahmenbedingungen vorgegebene Leistungsgrenzen möglichst gut auszunutzen. Ab dem Jahr 2000 wurde C++ aus der Domäne der Anwendungsprogrammierung von den SprachenJava undC# zurückgedrängt.
Die Sprache C++ verwendet nur etwa 60 Schlüsselwörter („Sprachkern“), manche werden in verschiedenen Kontexten (static,default) mehrfach verwendet. Ihre eigentliche Funktionalität erhält sie, ähnlich wie auch die Sprache C, durch dieC++-Standardbibliothek, die der Sprache fehlende wichtige Funktionalitäten beibringt (Arrays, Vektoren, Listen, …) wie auch die Verbindung zum Betriebssystem herstellt (iostream, fopen, exit, …). Je nach Einsatzgebiet kommen weitere Bibliotheken und Frameworks dazu. C++ legt einen Schwerpunkt auf die Sprachmittel zur Entwicklung von Bibliotheken. Dadurch favorisiert es verallgemeinerte Mechanismen für typische Problemstellungen und besitzt kaum in die Sprache integrierte Einzellösungen.
Eine der Stärken von C++ ist die Kombinierbarkeit von effizienter, maschinennaher Programmierung mit mächtigen Sprachmitteln, die einfache bis komplexe Implementierungsdetails zusammenfassen und weitgehend hinter abstrakten Befehlsfolgen verbergen. Dabei kommt vor allem dieTemplate-Metaprogrammierung zum Zuge: Eine Technik, die eine nahezu kompromisslose Verbindung von Effizienz und Abstraktion erlaubt.
Einige Design-Entscheidungen werden allerdings auch häufig kritisiert:
C++ hat keineGarbage Collection. Bis Version 20 gab es minimale Funktionalitäten für eine Garbage-Collection. Es gibt Bestrebungen, eine funktionale Garbage-Collection durch Bibliotheken oder durch Aufnahme in den Sprachstandard zu ermöglichen.[8][9][10] Siehe auchBoehm-Speicherbereinigung. Mit Version 23 wurde die im Code implementierte Garbage Collection vollständig entfernt.[11][12]
Es ist möglich, die Speicherverwaltung von C (malloc/realloc/free) zu verwenden; zur Implementierung von Low-Level-Funktionen in Bibliotheken wie der C++-Standardbibliothek ist dies zum Zugriff auf C Bibliotheksfunktionen notwendig. In allgemeinem C++-Code wird hiervon jedoch dringend abgeraten.[13]Stattdessen ist es dort üblich, die Speicherverwaltung von derC++-Standardbibliothek übernehmen zu lassen, indem man die angebotenen Containerklassen verwendet.
Andere Ressourcen, z. B.Dateihandles oderNetzwerksockets werden in C++ üblicherweise in eigenen Klassen mit dem PrinzipRAII verwaltet, um das automatische Aufräumen nach der Verwendung sicherzustellen.Dies ist konzeptionell in anderen Programmiersprachen oft mit der Implementierung spezieller Basisklassen/Schnittstellen gestaltet – wie z. B. „AutoCloseable“ in Java oder „IDisposable“ in C#.In anderen Programmiersprachen benötigen diese nicht verwalteten Ressourcen oft ein spezielles Handling (z. B. „using“-Schlüsselwort in C#), um die Lebenszeit dieser Objekte ausnahmesicher in Verbindung mit dem Garbage Collector zu verwalten.Die RAII-basierten Implementierungen in C++ sind konzeptbedingt nicht anfällig bezüglich dieser Probleme, da Speicher in C++ keinen Sonderstatus als Ressource hat. Eine korrekte Implementierung der Objektlebenszeit garantiert hier die Freigabe aller Ressourcen.
Für Verweise auf Objekte werden üblicherweise Referenzen verwendet, solange der Verweis das Objekt nicht besitzen soll – z. B. als Parameter bei Funktionsaufrufen.Um den Besitz von dynamisch allokierten Objekten zu verwalten, werden üblicherweiseSmart Pointer eingesetzt, welche die Destruktion und Speicherfreigabe übernehmen.Die Standardbibliothek unterscheidet hier strikt den Besitz. Während beimunique_ptr nur dieser Zeiger den Speicher besitzt, kann der Besitz des Speichers beimshared_ptr zwischen mehreren Zeigerinstanzen geteilt werden.Technisch realisiert ist dies beimshared_ptr meist mitReference counting.[14]
In C++ gehören private Eigenschaften (Variablen und Methoden) normalerweise mit zur Schnittstelle, die in der Header-Datei veröffentlicht ist. Dadurch entstehen zurCompilezeit und zurLaufzeit Abhängigkeiten der Objekte zu den Stellen, die sie verwenden.
Diese Abhängigkeiten können durch bestimmte Konstruktionen, wie dempimpl-Idiom (pointer to implementation idiom), vermieden werden. Dabei werden die privaten Felder der Klasse (example_class) in eine private, vorwärts-deklarierte Hilfsklasse verschoben, und ein Zeiger auf ein Objekt dieser Hilfsklasse (example_class::impl * impl_ptr) bleibt in der eigentlichen Klasse. Die Definition der implementierenden Klasse findet bei der Implementierung der öffentlichen Klasse statt und ist damit für den Verwender der Klasse (der nur die Header-Datei kennt) unsichtbar. Dadurch, dass die Hilfsklasse nur durch einen Zeiger referenziert wird, bleiben alle Quelltextänderungen an privaten Feldern transparent und dieBinärkompatibilität wird erhalten.[15]
Das Verhalten von einigen Sprachkonstrukten ist nicht definiert. Dies bedeutet, dass der Standard weder vorgibt noch empfiehlt, was in einem solchen Fall passiert. Die Auswirkungen reichen von Implementierungsabhängigkeit (d. h. je nach Zielrechner und Compiler kann sich das Konstrukt unterschiedlich verhalten) über unsinnige Ergebnisse oder Programmabstürze bis hin zu Sicherheitslücken. Einige dieser Freiheiten desCompilers lassen zusätzliche Optimierungen des Codes zu.
verschiedenen Optimierungseinstellungen (Debug, Release, Optimierung)
ausgewählterBefehlssatz, Aufrufkonventionen, u. v. a. m.
Quellcode mit Codepassagen mit undefiniertem Verhalten kann nach der Kompilierung unerwartetes und absurd erscheinenden Verhalten zeigen. So werden zu spät durchgeführte Überprüfungen wegoptimiert oder Schleifen, die auf einen ungültigen Index eines Arrays zugreifen, durch leere Endlosschleifen ersetzt.[16][17]
Wichtig für das Verständnis von undefiniertem Verhalten ist insbesondere, dass niemals nur eine einzelne Operation ungültig ist, sondern dasgesamte Programm ungültig wird und kein wohlgeformtes C++ mehr darstellt. Der Grund ist, dass manche Arten von „undefiniertem Verhalten“ Auswirkungen auf ganz andere, auch in sich korrekte, Programmteile haben und deren Verhalten beeinflussen können, beispielsweise bei Pufferüberläufen oder der unbeabsichtigten Änderung von Prozessor-Flags, die durch eine ungültige arithmetische Operation verursacht wurde und die nachfolgenden Berechnungen beeinflussen kann.
Beispiele fürundefiniertes Verhalten:
Überlauf von vorzeichenbehafteten Ganzzahlen (auch z. B. bei Umwandlung vonunsigned int nachint)
Schiebeoperationen mit einer Schiebeweite, die negativ oder größergleich der Zahl der Bits des zu schiebenden Typs ist
Division durch null mit integralen Datentypen
Weglassen desreturn-Statements in Funktionen mit Rückgabewert (die Hauptfunktionmain bildet die einzige Ausnahme)
Ein Nebeneffekt ändert eine Variable, die mehrmals in dem Ausdruck (v[i] = i++;) oder in derArgumentliste (f(i, i++);) vorkommt (die Auswertungsreihenfolge von Teilausdrücken und Funktionsargumenten ist nicht festgelegt)
Einerseits ist das hieraus resultierende nichtdeterministische Laufzeitverhalten, insbesondere bei kleinen Änderungen der Plattform, mindestens als Risiko, in der Praxis oft aber als klarer Nachteil einzustufen. Andererseits werden hierdurch schnellere Programme ermöglicht, da Gültigkeitsüberprüfungen weggelassen werden können und der Compiler zudem oft Programmteile stärker optimieren kann, indem er Randfälle als per Definition ausgeschlossen ignoriert.
Ein oft nicht wahrgenommener Vorteil ist darüber hinaus, dass dadurch, dass undefiniertes Verhalten praktisch nur in äußerst fragwürdigen Konstrukten auftritt, die aber nicht zwingend während des Kompilierens feststellbar sind, unsemantischer oder anderweitig suboptimaler Code gewissermaßen verboten wird.
Beispielsweise besteht eine illegale Art zu prüfen, ob die Summe zweier positiver Ganzzahlen und vom Typ ‚int‘ verlustfrei wieder in einem ‚int‘ abgebildet werden kann, daraus, zu schauen, ob ihre Summe größer 0 ist (bei Überlauf entsteht auf den meisten Computern durch dieZweierkomplement-Arithmetik eine negative Zahl). Eine derartige Überprüfung ist allerdings aus mathematischer Sicht nicht besonders sinnvoll. Eine bessere (semantischere) Herangehensweise ist hier, die eigentliche Frage, ob, wobei die größte in einem ‚int‘ darstellbare Zahl ist, nach der mathematisch validen Umformung zu zu verwenden.[18]
Um an die Verbreitung der Programmiersprache C anzuknüpfen, wurde C++ als Erweiterung vonC gemäß dem damaligen Stand von 1990 (ISO/IEC 9899:1990, auch kurz C90 genannt) entworfen.
Die Kompatibilität mit C zwingt C++ zur Fortführung einiger dadurch übernommener Nachteile. Dazu zählt die teilweise schwer verständliche C-Syntax, der als überholt geltendePräprozessor sowie verschiedene von der jeweiligen Plattform abhängige Details der Sprache, die die Portierung von C++-Programmen zwischen unterschiedlichen Rechnertypen, Betriebssystemen und Compilern erschweren.
Einige C-Sprachkonstrukte haben in C++ eine leicht abgewandelte Bedeutung oder Syntax, so dass manche C-Programme erst angepasst werden müssen, um sich als C++-Programm übersetzen zu lassen. Weitere Änderungen an C fanden in den Jahren 1999 (ISO/IEC 9899:1999, aka C99) und 2011 (ISO/IEC 9899:2011, aka C11) also nach der ersten Normung von C++ statt, so dass dort eingeflossene Änderungen nicht in C++98 berücksichtigt werden konnten. In die C++-Revision von 2011 wurde ein Teil der Neuerungen von C99 übernommen; auf der anderen Seite wurden dem C-Standard neue Features hinzugefügt, die auch mit C++11 nicht kompatibel sind.
DerPräprozessorbefehl oder auch Präprozessordirektive genannt#include bindetHeader-Dateien ein, die typischerweise Deklarationen von Variablen, Typen und Funktionen enthalten. Im Gegensatz zu C besitzen Header der C++-Standardbibliothek keine Dateiendung.
Der Header<iostream> ist Teil der C++-Standardbibliothek und deklariert unter anderem den Standardeingabestromstd::cin und die Standardausgabeströmestd::cout undstd::cerr für die aus der C-Standardbibliothek bekannten Objektestdin,stdout undstderr.
Beimain() handelt es sich um dieFunktion, die denEinsprungpunkt jedes C++-Programms darstellt. Das Programm wird ausgeführt, indem die Funktionmain() aufgerufen wird, wobei diese ihrerseits andere Funktionen aufrufen kann. Die Funktionmain() selbst darf allerdings in einem C++-Programm nichtrekursiv aufgerufen werden.
Der Standard verlangt von Implementierungen, zweiSignaturen für die Funktionmain() zu unterstützen: Eine ohne Funktionsparameter wie im Beispiel, und eine, die einen Integer und einen Zeiger auf Zeiger aufchar entgegennimmt, um aufKommandozeilenparameter zugreifen zu können (was nicht in allen Programmen vonnöten ist):int main(int argc, char **argv). Implementierungen dürfen darüber hinaus weitere Signaturen fürmain() unterstützen, alle müssen jedoch den Rückgabetypint (Integer) besitzen, also eine Ganzzahl zurückgeben. Würdemain() keinen Wert zurückgeben, schreibt der C++-Standard der Implementierung vor,return 0; anzunehmen.main() gibt also 0 zurück, wenn kein anderslautendesreturn-Statement in ihr vorhanden ist.[19]
std::cout ist eineInstanz der Klassestd::basic_ostream<char>, die sich wie die gesamte C++-Standardbibliothek imNamensraumstd befindet. Bezeichner in Namensräumen werden mit dem Bereichsoperator (::) angesprochen.
Die Ausgabe desZeichenkettenliterals"Hallo Welt" übernimmt der Operator<<. Zeichenkettenliterale sind in C++ vom TypArray aus N konstanten chars (char const[N]), wobeiN gleich der Länge der Zeichenkette + 1 für die abschließendeNullterminierung ist. Da dieStandardtypumwandlungen von C++ die alspointer-to-array decay bekannte implizite Umwandlung eines ArraysT[N] in einen PointerT* vorsehen, und damitchar const[N] in einenchar const* zerfällt, passt derüberladene Operatortemplate<class traits> basic_ostream<char,traits>& operator<<(std::basic_ostream<char,traits>&, char const *); aus<ostream> und wird entsprechend aufgerufen (operator<<( std::cout, "Hallo Welt!" );) und gibt die Zeichenkette aus. Durch den Ausgabemanipulatorstd::endl wird einZeilenendezeichen ausgegeben.
Beireturn 0 wird dem aufrufenden Programm über das Betriebssystem mitgeteilt, dass die Ausführung des Programms erfolgreich war.
Die Implementierung eines C++-Compilers gilt als aufwendig. Nach der Fertigstellung der Sprachnorm 1998 dauerte es mehrere Jahre, bis die Sprache von C++-Compilern weitestgehend unterstützt wurde.
Zu den verbreitetsten C++-Compilern gehören:
Visual C++
Der in MicrosoftVisual C++ enthaltene Compiler ist der am weitesten verbreitete für das BetriebssystemWindows. Die Community-Edition stellt Microsoft kostenlos zur Verfügung.
GCC
Der g++ ist die C++-Ausprägung derGNU Compiler Collection (GCC); g++ ist quelloffen und frei verfügbar. Der g++ unterstützt eine Vielzahl von Betriebssystemen (darunterUnix,Linux,macOS,Windows undAmigaOS) und Prozessorplattformen.GNU C++ existiert seit 1987 und ist somit einer der ältesten C++-Compiler.[20]
Clang
Clang, ein C++ Compiler-Frontend für plattformübergreifende CompilerinfrastrukturLLVM, die unter anderem auch in der Apple eigenen integrierten EntwicklungsumgebungXcode verwendet wird.[21] Im Clang/LLVM Ecosystem sind auch mehrere Tools zur statischen Codeanalyse entstanden wie z. B. „clang-tidy“ und „clang-format“.
Intel C++ Compiler
DerIntel C++ Compiler verwendet ebenfalls das unten erwähnte C++-Front-End von EDG. DerIntel C++ Compiler erzeugtMaschinencode für dieIntel-Prozessoren unter den Betriebssystemen Windows, Linux und macOS. Da die mit demIntel C++ Compiler erzeugten Programme den Befehlssatz der Intel-Prozessoren besonders gut ausnutzen, erzeugen sie besonders effiziente Programme für diese Plattform. (Kompilate des Intel-Compilers laufen ebenfalls aufAMD-Chips meist schneller als Kompilate der alternativen Compiler, entsprechende Optimierungsflags sperrt Intel jedoch, wobei sich die Sperre aufheben lässt.) Der Intel C++ Compiler nutzt im Unterbau wesentliche Teile des g++ und ersetzt und erweitert Teile der Code-Optimierung und Code-Generierung.
DerComeau C++. Das sogenannte „Front-End“ des Compilers, also der Teil, der die Analyse-Phase implementiert, wurde von der FirmaEdison Design Group (EDG) entwickelt, die sich auf die Entwicklung von Compiler-Front-Ends spezialisiert hat und deren C++-Front-End auch in vielen anderen kommerziellen C++-Compilern integriert ist. Der Comeau-Compiler kann auch über das Internet ausprobiert werden.
C++ war nicht der einzige Ansatz, die Programmiersprache C um Eigenschaften zu erweitern, die das objektorientierte Programmieren vereinfachen. In den 1980er Jahren entstand die ProgrammierspracheObjective-C, die sich aber im Gegensatz zu C++ syntaktisch wie von ihrem Funktionsprinzip anSmalltalk und nicht anSimula orientierte. Die Syntax von Objective-C (C beeinflusst durch Smalltalk) unterscheidet sich erheblich von C++ (C beeinflusst von Simula mit ganz eigenen syntaktischen Erweiterungen). Ende der 1980er Jahre wurde Objective-C erstmals kommerziell inNeXTStep verwendet, in dem es einen zentralen Bestandteil darstellt. Heutzutage findet es in der ProgrammierschnittstelleOpenStep (bzw.Cocoa undGNUstep) sowie in den BetriebssystemeniOS undmacOS ein wichtiges Einsatzgebiet.
Die ProgrammiersprachenJava undC# verfügen über eine ähnliche, ebenfalls an C angelehnte Syntax wie C++,[24] sind auch objektorientiert und unterstützen seit einiger Zeit Typparameter. Trotz äußerlicher Ähnlichkeiten unterscheiden sie sich aber konzeptionell von C++ zum Teil beträchtlich.
Generische Techniken ergänzen die objektorientierte Programmierung um Typparameter und erhöhen so die Wiederverwertbarkeit einmal kodierter Algorithmen. Die generischen Java-Erweiterungen sind jedoch lediglich auf Klassen, nicht aber auf primitive Typen oder Datenkonstanten anwendbar. Demgegenüber beziehen die generischen Spracherweiterungen von C# auch die primitiven Typen mit ein. Dabei handelt es sich allerdings um eine Erweiterung für Generik zur Laufzeit, die die auf Kompilationszeit zugeschnittenen C++-Templates zwar sinnvoll ergänzen, nicht aber ersetzen können.
Gerade die generische Programmierung macht C++ zu einem mächtigenProgrammierwerkzeug. Während die objektorientierte Programmierung in Java und C# nach wie vor den zentralen Abstraktionsmechanismus darstellt, ist diese Art der Programmierung in C++ rückläufig. So werden tiefe Klassenhierarchien vermieden, und zu Gunsten der Effizienz und der Minimierung des Ressourcenverbrauchs verzichtet man in vielen Fällen aufPolymorphie, einen der fundamentalen Bestandteile der objektorientierten Programmierung.
Auf die Idee für eine neue Programmiersprache kam Stroustrup durch Erfahrungen mit der ProgrammierspracheSimula während seiner Doktorarbeit an derCambridge University. Simula erschien zwar geeignet für den Einsatz in großen Software-Projekten, die Struktur der Sprache erschwerte aber die Erstellunghocheffizienter Programme. Demgegenüber ließen sich effiziente Programme zwar mit der SpracheBCPL schreiben, für große Projekte war BCPL aber wiederum ungeeignet.
Mit den Erfahrungen aus seiner Doktorarbeit erweiterte Stroustrup in den AT&TBell Laboratories im Rahmen von Untersuchungen desUnix-Betriebssystemkerns in Bezug aufverteiltes Rechnen ab 1979 dieProgrammiersprache C. Die Wahl fiel auf die Programmiersprache C, da C eine Mehrzwecksprache war, die schnellen Code produzierte und einfach auf andere Plattformen zuportieren war. Als dem Betriebssystem Unix beiliegende Sprache hatte C außerdem eine erhebliche Verbreitung.
Eine der ersten Erweiterungen war einKlassenkonzept mit Datenkapselung, für das die SpracheSimula-67 das primäre Vorbild war. Danach kamen abgeleitete Klassen hinzu, ein strengeresTypsystem, Inline-Funktionen und Standard-Argumente.
Während StroustrupC with Classes („C mit Klassen“) entwickelte (woraus später C++ wurde), schrieb er auchcfront, einen Compiler, der ausC with Classes zunächst C-Code als Zwischenresultat erzeugte. Die erste kommerzielle Version voncfront erschien im Oktober 1985.
1983 wurdeC with Classes inC++ umbenannt. Erweiterungen darin waren: Überladen von Funktionsnamen und Operatoren, virtuelle Funktionen, Referenzen, Konstanten, eine änderbare Freispeicherverwaltung und eine verbesserte Typüberprüfung. Die Möglichkeit von Kommentaren, die an das Zeilenende gebunden sind, wurde aus BCPL übernommen (//).
1985 erschien die erste Version von C++, die eine wichtige Referenzversion darstellte, da die Sprache damals noch nicht standardisiert war. 1989 erschien die Version 2.0 von C++. Neu darin warenMehrfachvererbung, abstrakte Klassen, statische Elementfunktionen, konstante Elementfunktionen und die Erweiterung des Zugriffsmodells umprotected. 1990 erschien das BuchThe Annotated C++ Reference Manual, das als Grundlage für den darauffolgenden Standardisierungsprozess diente.
Relativ spät wurden der SpracheTemplates,Ausnahmebehandlung,Namensräume, neuartigeTypumwandlungen undboolesche Typen hinzugefügt.
Im Zuge der Weiterentwicklung der Sprache C++ entstand auch eine gegenüber C erweiterte Standardbibliothek. Erste Ergänzung war dieStream-I/O-Bibliothek, die Ersatz für traditionelle C-Funktionen wie zum Beispielprintf() undscanf() bietet. Eine der wesentlichen Erweiterungen der Standardbibliothek kam später durch die Integration großer Teile der beiHewlett-Packard entwickeltenStandard Template Library (STL) hinzu.
Nach jahrelanger Arbeit wurde schließlich 1998 die endgültige Fassung der Sprache C++ (ISO/IEC 14882:1998) genormt. Diese Version wurde im Nachhinein, als weitere Versionen der Sprache erschienen, auchC++98 genannt. Im Jahr 2003 wurde ISO/IEC 14882:2003 verabschiedet, eine Nachbesserung der Norm von 1998, in der einige Missverständnisse beseitigt und mehrere Details klarer formuliert wurden. Diese Version wird umgangssprachlich auchC++03 genannt.
Weiterentwicklung der Programmiersprache C++ nach 2005
Um mit den aktuellen Entwicklungen der sich schnell verändernden Computer-Technik Schritt zu halten, aber auch zur Ausbesserung bekannter Schwächen, erarbeitete das C++-Standardisierungskomitee die nächste größere Revision von C++, die inoffiziell mitC++0x abgekürzt wurde, worin die Ziffernfolge eine grobe Einschätzung des möglichen Erscheinungstermins andeuten sollte. Später, als ein Erscheinungstermin bis Ende 2009 nicht mehr zu halten war, änderte sich der inoffizielle Name zuC++1x.
Die vorrangigen Ziele für die Weiterentwicklung von C++ waren Verbesserungen im Hinblick auf die Systemprogrammierung sowie zur Erstellung von Programmbibliotheken. Außerdem sollte die Erlernbarkeit der Sprache für Anfänger verbessert werden.
Im November 2006 wurde der Zieltermin für die Fertigstellung auf das Jahr 2009 festgelegt. Im Juli 2009 wurde dieser Termin auf frühestens 2010 geändert. Im August 2011 wurde die Revision einstimmig von derISO angenommen[25] und am 11. Oktober 2011 als ISO/IEC 14882:2011 offiziell veröffentlicht.[26][27] Inoffiziell heißt die VersionC++11.
C++98 deckte einige typische Problemfelder der Programmierung noch nicht ausreichend ab, zum Beispiel die Unterstützung von Nebenläufigkeit (Threads), deren Integration in C++, insbesondere für die Verwendung in Mehrprozessorumgebungen, eine Überarbeitung der Sprache unumgänglich machte. Durch die Einführung eines Speichermodells wurden Garantien der Sprache für den nebenläufigen Betrieb festgelegt, um Mehrdeutigkeiten in der Abarbeitungsreihenfolge sowohl aufzulösen als auch in bestimmten Fällen aufrechtzuerhalten und dadurch Spielraum für Optimierungen zu schaffen.
Zu den weitreichenderen Spracherweiterungen gehörte ferner dieautomatische Typableitung zur Ableitung von Ergebnistypen aus Ausdrücken und die sogenanntenR-Wert-Referenzen, mit deren Hilfe sich als Ergänzung zu dem bereits vorhandenenKopieren von Objekten dann auch einVerschieben realisieren lässt, außerdem bereichsbasierte For-Schleifen (foreach) über Container und eingebaute Felder.[28]
Im April 2006 gab das C++-Standardisierungskomitee den sogenannten ersten Technischen Report (TR1) heraus, eine nicht normative Ergänzung zur aktuell gültigen, 1998 definierten Bibliothek, mit der Erweiterungsvorschläge vor einer möglichen Übernahme in dieC++-Standardbibliothek auf ihre Praxistauglichkeit hin untersucht werden sollen. Viele Compiler-Hersteller lieferten den TR1 mit ihren Produkten aus.
Im TR1 waren u. a.reguläre Ausdrücke,[29] verschiedeneintelligente Zeiger,[30]ungeordnete assoziativeContainer,[31] eine Zufallszahlenbibliothek,[32] Hilfsmittel für die C++-Metaprogrammierung,Tupel[33] sowienumerische und mathematische Bibliotheken enthalten.[34] Die meisten dieser Erweiterungen stammten aus derBoost-Bibliothek, woraus sie mit minimalen Änderungen übernommen wurden. Außerdem waren sämtliche Bibliothekserweiterungen der 1999 überarbeiteten Programmiersprache C (C99) in einer an C++ angepassten Form enthalten.[35]
Mit Ausnahme der numerischen und mathematischen Bibliotheken wurden alle TR1-Erweiterungen in die Sprachnorm C++11 übernommen. Ebenfalls wurde eine eigene Bibliothek zur Unterstützung von Threads eingeführt.
Mit der Norm ISO/IEC 14882:2011, auch bekannt alsC++11, wurden viele weitreichende Neuerungen in C++ eingeführt, wie auszugsweise:
Lambdas (Anonyme Funktionen), welche vor der Verabschiedung desC++11-Standards in anderen Sprachen schon teils breite Anwendung fanden, erweitern die Sprache vor allem im Bereich der funktionalen Programmierung.
Eine erleichterte Typbehandlung mitTypinferenz ist nun über das Schlüsselwortauto (das nun nicht mehr ein Speicherklassen-Specifier ist) einerseits und das Schlüsselwortdecltype (das den Typ eines Ausdrucks statisch zur Compilezeit zurückgibt, sofern ermittelbar) andererseits möglich. Beide Schlüsselworte zeigen ihre Stärke zudem auch im Verbund. So können ganze Funktionen, deren Rückgabetypen beispielsweise nur schwer vom Programmierer einzusehen sind, weil sie beispielsweise innerhalb komplexerer Klassentemplates liegen, komfortabel definiert werden:
Streng typisierteenums (enum class) beseitigen Probleme mit Namenskollisionen und schränken die Fehleranfälligkeit in Bezug auf implizite Typkonvertierungen ein.
Sogenannte „range-based loops“ mittels eines modifiziertenfor-Statements erleichtern die Arbeit mit Containern und Arrays in der Art, dass Iteratoren beim Traversieren von Objekten dieser Datentypen für viele Anwendungsfälle überflüssig werden:
Es dürfen direkt aufeinanderfolgende spitze Klammern bei Templates benutzt werden:map<int, vector<int>>.
Überdies erfolgte mit der Einführung von variadischen (vielstelligen) Templates eine großräumige Erweiterung der Nutzungsmöglichkeiten von Templates. Diese ermöglichen nun eine nicht fixe Anzahl von Template-Argumenten template<typename... Values> class VariadicExampleClass;, was weitreichende Optionen und Vereinfachungen im Code- bzw. Algorithmenaufbau und der Codestruktur allgemein ermöglicht. Des Weiteren haben sie, wie viele andereC++11-Erweiterungen auch, das Potential, die Notwendigkeit zur Nutzung von teils fehleranfälligen und nicht robusten Macros weiter einzuschränken.
Die explizite Nutzbarkeit sogenannter Rvalue-Referenzen ermöglicht, aufbauend unter anderem auf sogenannter Bewegungssemantik, ein breites Spektrum von Codevereinfachungen, Laufzeitoptimierungen und ausnahmesicherer Programmierung. Mit den Rvalue-Referenzen wurden auch die sogenannten universellen Referenzen eingeführt, welche das Problem des „Perfect forwarding“ auf Sprachebene robust und einfach lösbar machen (die konsistente Weiterreichung von Typen innerhalb von Templatekonstrukten, die per „type deduction“ aufgelöst wurden, an weiterführende Templates). Vor der Verabschiedung desC++11-Standards war dies zumindest rein auf Sprachebene nicht möglich und erforderte vom Programmierer je nach Problemfall mehr oder weniger viel Eigenregie mit teils entsprechender Codeaufblähung und -Duplizierung.
Außerdem wurden einige Features aus C11 übernommen, zum Beispiel Ganzzahlen mit mindestens 64 Bit (long long) oder Zusicherungen zur Übersetzungszeit mittelsstatic_assert (in C11:_Static_assert).[36]
Themen der Sprache C++, die Rechenzeit und Speicherplatz betreffen, wurden im sogenanntentechnical report ISO/IEC TR 18015:2006 behandelt.[37]
Zum Zeitpunkt der Einführung des Standards und auch noch vergleichsweise lange darüber hinaus unterstützten viele gängige Compiler diesen nicht vollständig bzw. mit Bezug auf einige Erweiterungen mitunter fehlerhaft. Besonders starke Einschränkungen zeigte diesbezüglich zum Beispiel Microsoft mitVisual C++ 2012. MitVisual C++ 2015 sind mittlerweile jedoch nahezu alle wichtigen größeren Spracherweiterungen berücksichtigt worden.[38][39]
C++14, beschrieben im Standard ISO/IEC 14882:2014,[2] erweitert die Einsatzmöglichkeiten vonauto unddecltype, schwächt die Voraussetzungen fürconstexpr ab, erlaubt Variablen-Templates zu definieren (beispielsweise um mehrere Versionen von π mit je nach Typ unterschiedlicher Genauigkeit zu definieren), führt Binärliterale ein (0b...), führt Hochkommata als Trennzeichen in Zahlen ein, erlaubt generische Lambdas, erweitert Lambda capture expressions und führt das Attributdeprecated ein.[2]
Außerdem wurde die Standardbibliothek um ein paar Funktionen ergänzt, die bei C++11 „vergessen“ bzw. „übersehen“ wurden (z. B.std::make_unique) und etliche Funktionsdeklarationen nun alsconstexpr umdeklariert, was dem Compiler aggressivere Optimierungen gestattet.
Während der Entwicklungsphase wurde C++14 auchC++1y genannt, um anzudeuten, dass es die Nachfolgeversion der vormals als C++0x genannten Version sein wird.
Im März 2017 hat das ISO-C++-Komitee den Sprachstandard C++17 technisch abgeschlossen. Für die neue Fassung wurde unter anderem die Aufnahme des Typenstd::byte beschlossen.[40] Dieser ist explizit für den byte-weisen Zugriff auf den Speicher bestimmt. Es wurden neue, generische Container eingeführt:std::any als Alternative zuvoid* mit Typüberprüfung zur Laufzeit,std::variant als Alternative zur aus C übernommenen Union mit Laufzeit-Typprüfung undstd::optional, ein Container, der genau ein Element enthalten kann, aber nicht muss.
Bis zur offiziellen Verabschiedung wurde die Fassung auch alsC++1z bezeichnet.[41]
Nach dem Sommer-Meeting Mitte Juli verriet der C++-ExperteHerb Sutter, der für die Einberufung des Komitees verantwortlich ist, in seinem Blog[42] bereits erste Pläne für C++20.
ein Modulsystem zur Codekapselung und kürzeren Kompilierzeiten[44]
std::format zur String-Interpolation. Es handelt sich um typsicheren und durch den Benutzer erweiterbaren Ersatz für sprintf und stringstreams, der sich stark an Python anlehnt.
std::span als Verallgemeinerung des Konzeptes von string_view (C++17). Einspan beschreibt einen Speicherbereich durch einen Pointer und eine Größenangabe.
Der Name C++ ist eine Wortschöpfung von Rick Mascitti, einem Mitarbeiter Stroustrups, und wurde zum ersten Mal im Dezember 1983 benutzt. Der Name kommt von der Verbindung der Vorgängersprache C und demInkrement-Operator++, der den Wert einer Variablen inkrementiert (um eins erhöht). Der Erfinder von C++, Bjarne Stroustrup, nannte C++ zunächst „C mit Klassen“(C with classes).[46]
Oft geäußerte Kritik an der Sprache umfasst beispielsweise:
C++ sei sehr komplex und fehleranfällig zu programmieren. Man müsse viel lernen und üben, um es gut zu beherrschen, und viele Features gelten als äußerst komplex.[47]
C++ sei zulow-level-mäßig aufgebaut; während es viele Features von höher abstrahierenden Sprachen aufweist (Klassen, generische Klassen/Funktionen etc.), seien als wichtig empfundene Dinge, insbesondereGarbage Collection, nicht vorhanden.[8]
C++ gilt zwar als schnell, beispielsweise wegen der Möglichkeit, frei mit Pointern zu arbeiten, doch diese Leistung sei auf den heutigen, schnellen Computersystemen nur in Ausnahmefällen nötig: Während es sinnvoll sei, Betriebssysteme o. Ä. in C++ zu schreiben, sei es softwaretechnisch viel günstiger, Anwendungsprogramme inhöheren Sprachen zu schreiben, da diese leichter zu warten seien und immer noch eine ausreichende Leistung aufwiesen.[48]
Typisch in Verbindung mit C++ ist das Zitat von Bjarne Stroustrup:
“In C++ it’s harder to shoot yourself in the foot, but when you do, you blow off your whole leg.”
„In C++ ist es schwieriger, sich selbst in den Fuß zu schießen, aber wenn man es tut, dann ist gleich das ganze Bein weg.“[49]
Soll heißen: C++ erleichtert zunächst vieles, aber es bringt gleichzeitig viele Mittel mit sich, die mit Bedacht eingesetzt werden müssen. Zum Beispiel können durch die dynamische Speicherallokation ohneautomatische SpeicherfreigabeSpeicherlecks entstehen. Zeiger können auf falsche Speicherbereiche verweisen und verstecktes Fehlverhalten erzeugen (Hängender Zeiger).
Embedded C++, ein Dialekt von C++, bei dem einige Sprachfeatures und Bibliotheksfunktionen entfernt wurden, um füreingebettete Systeme geeigneter zu sein.
Bjarne Stroustrup:Die C++-Programmiersprache: Aktuell zu C++11. Carl Hanser, 2015,ISBN 978-3-446-43961-0 (Standardwerk zu C++, Grundkenntnisse in C von Vorteil).
Bjarne Stroustrup:The Design and Evolution of C++. Addison-Wesley, 1994,ISBN 0-201-54330-3 (Buch beschreibt die Entwicklung und das Design von C++; vom Sprachdesigner geschrieben).
Bjarne Stroustrup:Programming – Principles and Practice Using C++. 3. überarbeitete Auflage. Addison-Wesley, 2024,ISBN 978-0-13-830868-1 (Einführung in die Programmierung; Standardwerk für Einstiegsprogrammierkurse an der Universität Texas A&M).
Andrei Alexandrescu:Modernes C++ Design – Generische Programmierung und Entwurfsmuster angewendet. 1. Auflage. Mitp-Verlag, 2003,ISBN 3-8266-1347-3 (Ein Standardwerk zurC++-Metaprogrammierung, setzt ein tiefes Verständnis von C++ voraus.).
Ulrich Breymann:C++ programmieren: C++ lernen – professionell anwenden – Lösungen nutzen. 7. überarbeitete Auflage. Carl Hanser, 2023,ISBN 978-3-446-47689-9 (C++-Einführung aus dem Hochschulumfeld).
Sibylle Schupp:A Semantic Definition of Separate Type Checking in C++ with Concepts. (wissenschaftlicher Artikel). In:Journal of Object Technology.Band8,Nr.5, 2009,S.105–132,doi:10.5381/jot.2009.8.5.a2.
↑abBjarne Stroustrup: Proposal to Acknowledge that Garbage Collection for C++ is Possible. (PDF) 1996, abgerufen am 6. Juni 2015 (englisch): „The most loudly proclaimed fundamental weakness of C++ these days is the absence of automatic garbage collection. This criticism is harming C++’s reputation, scaring potential users away, and restricting the range of applications for which C++ is a strong contender as an implementation language. For many applications automatic garbage collection is indeed a very powerful tool and the right tool for the job.“
↑Ian Joyner: C++?? A Critique of C++. (PDF) November 1992, S. 27–29, abgerufen am 6. Juni 2015 (englisch).
↑The Problem With C++. In: www.codinghorror.com. 12. Januar 2007, archiviert vom Original (nicht mehr online verfügbar) am 26. Februar 2014; abgerufen am 22. September 2018 (englisch).Info: Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäßAnleitung und entferne dann diesen Hinweis.@1@2Vorlage:Webachiv/IABot/www.codinghorror.com