Unterstützung für C++11-Funktionen (Modern C++)
In diesem Artikel werden C++11-Funktionen in Visual C++ beschrieben.
In diesem Artikel
C++11 Feature List
Core Language Feature Table
Core Language Feature Table: Concurrency
Core Language Feature Table: C99
Guide To Feature Tables
Rvalue References
Lambdas
decltype
Strongly Typed/Forward Declared enums
Alignment
Standard-Layout and Trivial Types
Defaulted and deleted functions
override and final
Atomics, and more
C99 __func__ and preprocessor rules
Standard Library features
C++11-Funktionsliste
Visual C++ in Visual Studio 2010 hat viele Funktionen in der C++11-Kernsprachenspezifikation implementiert, und in Visual C++ in Visual Studio 2012 wurden weitere Funktionen hinzugefügt. Visual C++ in Visual Studio 2013 erweitert diese Abdeckung weiter und unterstützt auch einige Funktionen der C++14-Bibliothek. In der folgenden Tabelle sind die C++11-Kernsprachenfunktionen und deren Implementierungsstatus in Visual C++ in Visual Studio 2010, Visual C++ in Visual Studio 2012 und Visual C++ in Visual Studio 2013 aufgelistet.
Funktionstabelle der C++11-Kernsprache
Visual Studio 2010 |
Visual Studio 2012 |
Visual Studio 2013 |
|
---|---|---|---|
v2.0 |
v2.1* |
v2.1* |
|
Nein |
Nein |
Nein |
|
Nein |
Nein |
||
Nein |
Nein |
||
Nein |
Nein |
||
Ja |
Ja |
Ja |
|
v1.0 |
v1.0 |
v1.0 |
|
Ja |
Ja |
Ja |
|
v1.0 |
v1.1 |
v1.1 |
|
v1.0 |
v1.1** |
v1.1 |
|
Ja |
Ja |
Ja |
|
Nein |
Nein |
Ja |
|
Nein |
Nein |
Nein |
|
Nein |
Nein |
||
Ja |
Ja |
Ja |
|
Ja |
Ja |
Ja |
|
Partial |
Ja |
Ja |
|
Nein |
Ja |
Ja |
|
Nein |
Nein |
Nein |
|
Nein |
Nein |
Nein |
|
TR1 |
Partial |
Partial |
|
Nein |
Nein |
||
Nein |
Nein |
Nein |
|
Nein |
Nein |
Ja |
|
Nein |
Nein |
Nein |
|
Nein |
Nein |
Nein |
|
Nein |
Nein |
||
Nein |
Nein |
Nein |
|
Nein |
Nein |
Nein |
|
Nein |
Ja |
Ja |
|
Nein |
Nein |
||
Ja |
Ja |
Ja |
|
Nein |
Nein |
Nein |
|
Nein |
Nein |
Nein |
|
Nein |
Nein |
Nein |
|
Ja |
Ja |
Ja |
|
Nein |
Ja |
Ja |
|
Partial |
Ja |
Ja |
|
Ja |
Ja |
Ja |
|
Nein |
Nein |
Nein |
[go to top]
Funktionstabelle für C++11-Kernsprachfunktionen: Nebenläufigkeit
Features der C++11-Kernsprache: Nebenläufigkeit |
Visual Studio 2010 |
Visual Studio 2012 |
Visual Studio 2013 |
---|---|---|---|
Nicht zutreffend |
Nicht zutreffend |
Nicht zutreffend |
|
Nein |
Ja |
Ja |
|
Nein |
Ja |
Ja |
|
Nein |
Ja |
Ja |
|
Nicht zutreffend |
Nicht zutreffend |
Nicht zutreffend |
|
Nein |
Ja |
Ja |
|
Nein |
Nein |
Nein |
|
Ja |
Ja |
Ja |
|
Nein |
Nein |
Nein |
|
Nein |
Nein |
Nein |
|
Partial |
Partial |
Partial |
|
Nein |
Nein |
Nein |
[go to top]
Features der C++11-Kernsprache: C99
Features der C++11-Kernsprache: C99 |
Visual Studio 2010 |
Visual Studio 2012 |
Visual Studio 2013 |
---|---|---|---|
Partial |
Partial |
Partial |
|
Partial |
Partial |
Partial |
|
Ja |
Ja |
Ja |
|
Nicht zutreffend |
Nicht zutreffend |
Nicht zutreffend |
[go to top]
Leitfaden zu den Funktionstabellen
rvalue-Referenzen
Hinweis
Die Versionsbezeichnungen in den folgenden Beschreibungen (v0.1, v1.0, v2.0, v2.1 und v3.0) wurden aus Gründen der Übersichtlichkeit eingeführt und zeigen die Entwicklung von C++11.Der Standard selbst verwendet sie nicht.
N1610 "Clarification of Initialization of Class Objects by rvalues" war ein früher Versuch, Verschiebesemantik ohne rvalue-Referenzen zu ermöglichen. In dieser Diskussion soll sie "rvalue-Referenz v0.1" genannt werden. Sie wurde ersetzt durch "rvalue-Referenzen v1.0." "rvalue-Referenzen v2.0", auf dem die Arbeit in Visual C++ in Visual Studio 2010 basiert, verhindert die Bindung von rvalue-Referenzen an lvalues und behebt damit ein schwerwiegendes Sicherheitsproblem. " Rvalue-Referenzen v2.1" entwickelt diese Regel weiter. Betrachten Sie vector<string>::push_back() mit den Überladungen push_back(const string&) und push_back(string&&), dazu den Aufruf v.push_back("strval"). Der Ausdruck "strval" ist ein Zeichenfolgenliteral, und er ist ein lvalue. (Andere Literale, beispielsweise die Ganzzahl 1729, sind rvalues, aber Zeichenfolgenliterale sind speziell, da sie Arrays sind.) Die Regeln aus "rvalue-Referenzen v2.0" besagen, dass string&& nicht an "strval" gebunden werden kann, da "strval" ein lvalue ist, und daher push_back(const string&) die einzige realisierbare Überladung ist. Dies würde einen temporären std::string erstellen, ihn in den Vektor kopieren und std::string anschließend zerstören, was nicht effizient wäre. Die "rvalue-Referenzen v2.1"-Regeln erkennen, dass die Bindung von string&& an "strval" einen temporären std::string erstellen würde, und dass dieser ein rvalue ist. Daher sind push_back(const string&) und push_back(string&&) realisierbar, und push_back(string&&) wird bevorzugt. Ein temporärer std::string wird erstellt und dann in den Vektor verschoben. Dies ist effizienter.
"rvalue-Referenzen v3.0" fügt neue Regeln hinzu, um Verschiebungskonstruktoren und Verschiebungszuweisungsoperatoren unter bestimmten Bedingungen automatisch zu generieren. Diese sind aus Zeit- und Ressourcenmangel jedoch noch nicht in Visual C++ in Visual Studio 2013 implementiert.
[go to top]
Lambdas
Nachdem Lambda-Funktionen in das Arbeitspapier (Version "0.9") gewählt und änderbare Lambdas hinzugefügt wurden (Version "1.0"), hat der Standardisierungsausschuss die Formulierung überarbeitet. Das führte zu Lambdas Version "1.1", die jetzt vollständig unterstützt werden. Die Formulierung "Lambdas v1.1" erläutert, wie in Sonderfällen (Verweis auf statische Member oder geschachtelte Lambdas) verfahren werden sollte. Hierdurch werden Probleme behoben, die durch komplexe Lambdas ausgelöst werden. Darüber hinaus können zustandslose Lambdas nun in Funktionszeiger konvertiert werden. Dies ist nicht die Formulierung N2927, wird jedoch als Teil von "Lambdas v1.1" angesehen. C++11 5.1.2 [expr.prim.lambda]/6 enthält folgende Beschreibung: "Der Closure-Typ für einen lambda-expression ohne lambda-capture besitzt eine öffentliche, nicht virtuelle, nicht explizite Umwandlungsfunktion für const in Zeiger und kann dadurch dieselben Parameter und Rückgabetypen verwenden wie der Funktionsaufrufoperator des Closure-Typs. Der von dieser Umwandlungsfunktion zurückgegebene Wert soll die Adresse einer Funktion sein, deren Aufruf denselben Effekt hat wie der Aufruf des Funktionsaufrufoperators des Closure-Typs." (Die Visual C++ in Visual Studio 2012-Implementierung ist sogar noch besser, weil damit jetzt zustandslose Lambdas in Funktionszeiger konvertiert werden können, die beliebige Aufrufkonventionen besitzen. Dies ist wichtig, wenn Sie APIs verwenden, die Elemente wie __stdcall-Funktionszeiger erwarten.)
[go to top]
decltype
Nachdem "decltype" in das Arbeitspapier (Version 1.0) gewählt wurde, gab es dafür in letzter Minute eine kleine, jedoch wichtige Fehlerkorrektur (Version 1.1). Dies ist vom großen Interesse für Programmierer, die mit STL und Boots arbeiten.
[go to top]
Stark typisierte und vorwärts deklarierte Enumerationen
Stark typisierte Enumerationen wurden teilweise in Visual C++ in Visual Studio 2010 unterstützt (dort speziell im Teil über explizit angegebene zugrunde liegende Typen). Diese werden jetzt vollständig in Visual Studio implementiert, und die C++11-Semantik für vorwärts deklarierte Enumerationen ist ebenfalls vollständig implementiert.
[go to top]
Ausrichtung
Die Kernsprachenschlüsselwörter alignas/alignof aus dem alignment-Vorschlag, der in das Arbeitspapier gewählt wurde. Visual C++ in Visual Studio 2010 verfügte über aligned_storage aus TR1. In Visual C++ in Visual Studio 2012 wurden aligned_union und std::align() zur Standardbibliothek hinzugefügt und in Visual C++ in Visual Studio 2013 wurden wichtige Fehler behoben.
[go to top]
Standardlayout- und einfache Typen
Die verfügbar gemachten Änderungen aus N2342 "POD's Revisited; Resolving Core Issue 568 (Revision 5)" sind die Ergänzungen von is_trivial und is_standard_layout zur Bibliothek der Standardvorlage <type_traits>. (In N2342 wurden viele Benennungen der Kernsprache überarbeitet, Compileränderungen waren jedoch nicht erforderlich.) Diese Typmerkmale waren in Visual C++ in Visual Studio 2010 verfügbar, aber sie duplizierten einfach is_pod. Daher ist in der oben dargestellten Tabelle bezüglich der Unterstützung "Nein" angegeben. Sie werden nun durch Compilerhooks unterstützt, die entwickelt wurden, um genaue Antworten zu geben.
Der common_type<> von STL erhielt eine dringend erforderliche Korrektur in Visual C++ in Visual Studio 2013. Die C++11-Spezifizierung für common_type<> hatte unerwarteten und unerwünschten Folgen. Insbesondere führte es dazu, dass common_type<int, int>::type int&& zurückgab. Daher implementiert Visual C++ in Visual Studio 2013 die Vorgeschlagene Lösung für das Bibliotheks-Arbeitsgruppenproblem 2141, bei der von common_type<int, int>::type int zurückgegeben wird.
Als Nebeneffekt dieser Änderung funktioniert der Identitätsfall nicht mehr (common_type<T> ergibt nicht immer den Typ T). Dies entspricht der vorgeschlagenen Lösung, beeinträchtigt jedoch den Code, der auf dem vorherigen Verhalten beruhte.
Wenn ein Identitätstypmerkmal erforderlich ist, verwenden Sie nicht std::identity, das kein Standard ist und in <type_traits> definiert ist, da es nicht bei <void> funktioniert. Implementieren Sie stattdessen Ihr eigenes Identitätstypmerkmal, um Ihre Anforderungen zu erfüllen. Im Folgenden ein Beispiel:
template <typename T> struct Identity {
typedef T type;
};
Hinweis
Weitere wichtige Änderungen finden Sie unter Wichtige Änderungen in Visual C++.
[go to top]
Defaulted- und Deleted-Funktionen
Diese werden jetzt unterstützt, allerdings mit folgender Ausnahme: Für Defaulted-Funktionen wird die Verwendung von =default zur Anforderung von Bewegungskonstruktoren und Bewegungszuweisungsoperatoren für jeden Member nicht unterstützt. Die Kopien und die Verschiebungen interagieren nicht präzise, wie im Standard vorgegeben. Durch Löschen von Verschiebungen sollen auch Kopien unterdrückt werden, was bei Visual C++ in Visual Studio 2013 jedoch nicht der Fall ist.
Weitere Informationen zur Verwendung von Defaulted- und Deleted-Funktionen finden Sie unter C++-Funktionsdefinitionen.
[go to top]
override und final
Hierzu gab es eine kurze, jedoch schwierige Entwicklung. In Version 0.8 gab es ursprünglich [[override]]-, [[hiding]]- und [[base_check]]-Attribute. Dann wurden in Version 0.9 die Attribute entfernt und durch kontextbedingte Schlüsselwörter ersetzt. In Version 1.0 wurden sie schließlich für Klassen auf "final" und für Funktionen auf "override" und "final" reduziert. Dadurch ergab sich eine aufsteigende Erweiterung, da Visual C++ in Visual Studio 2010 diese "override"-Syntax für Funktionen bereits unterstützte und sich die Semantik eng an die in C++11 anlehnte. "final" wurde ebenfalls unterstützt, jedoch mit der abweichenden Bezeichnung "sealed". Die Standardschreibweise und die Semantik von "override" und "final" werden nun vollständig unterstützt. Weitere Informationen finden Sie unter override-Bezeichner und final-Bezeichner.
[go to top]
Atomics und mehr
Atomics, starke compare_exchange-Operation, bidirektionale Fences und Datenabhängigkeits-Reihenfolge sind Elemente der Standardbibliothek, die nun implementiert sind.
Verwandte STL-Header: <atomic>, <chrono>, <condition_variable>, <future>, <mutex>, <ratio>, <scoped_allocator> und <thread>.
[go to top]
C99 __func__ und Präprozessorregeln
In der Tabelle Core Language Feature Table: C99 ist eine "partielle" Implementierung für zwei Elemente aufgelistet. Für den vordefinierten Bezeichner __func__ ist "partiell" aufgeführt, da die Unterstützung für die Nicht-Standarderweiterungen __FUNCDNAME__, __FUNCSIG__ und __FUNCTION__ bereitgestellt wird. Weitere Informationen finden Sie unter Vordefinierte Makros. Für C99-Präprozessorregeln ist "partiell" aufgeführt, weil variadic-Makros unterstützt werden. Weitere Informationen finden Sie unter Variadic-Makros.
[go to top]
Standardbibliotheksfeatures
Dies betrifft die Kernsprache. Für die C++11-Standardbibliothek existiert keine Funktionsvergleichstabelle, aber Visual C++ in Visual Studio 2012 implementiert sie, mit zwei Ausnahmen. Wenn eine Bibliotheksfunktion von Funktionen abhing, die im Compiler fehlten, wurde sie zunächst entweder simuliert – z. B. simulierte variadic-Vorlagen für make_shared<T>() – oder sie wurde nicht implementiert. (Es gab nur einige Fälle, vor allem <initializer_list>, die jetzt vollständig in Visual C++ in Visual Studio 2013 implementiert sind). Mit sehr wenigen Ausnahmen ist C99 in Visual C++ in Visual Studio 2013 implementiert und C++-Wrapperheader wurden bereitgestellt. Weitere Informationen finden Sie unter Unterstützung für die C99-Bibliothek in Visual Studio 2013.
Hier ist eine partielle Liste der Änderungen in Visual C++ in Visual Studio 2012 und Visual C++ in Visual Studio 2013:
Emplacement: Wie von C++11 gefordert, wurden emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() in allen Containern für eine "beliebige" Anzahl von Argumenten implementiert (siehe Abschnitt "Simulierte variadics"). Beispielsweise wird durch vector<T> mit "template <typename... Args> void emplace_back(Args&&... args)" direkt ein Element vom Typ T an den Vektor angefügt, mit einer beliebigen Anzahl von beliebigen Argumenten. Dies kann effizienter sein als push_back(T&&), weil hierbei eine zusätzliche Verschiebungskonstruktion und deren Zerstörung beteiligt sind.
Variadics: Visual C++ in Visual Studio 2012 verfügte über ein Schema zum Simulieren von variadic-Vorlagen. In Visual C++ in Visual Studio 2013 sind keine Simulationen mehr vorhanden und variadics sind vollständig implementiert. Wenn der Code auf dem alten simulierten variadics-Verhalten basiert, müssen Sie ihn korrigieren. Der Wechsel zu realen variadic-Vorlagen bringt verbesserte Kompilierzeiten und reduzierten Compilerspeicherverbrauch mit sich.
Explizite Konvertierungsoperatoren: In der Kernsprache stellen explizite Konvertierungsoperatoren eine allgemeine Funktion dar – z. B. ist explicit operator MyClass() möglich. Allerdings verwendet die Standardbibliothek derzeit nur ein Formular: explicit operator bool(), sodass Klassen sicher auf den Booleschen Wert getestet werden können. (Einfaches "operator bool()" ist offenkundig risikoreich.) Zuvor simulierte Visual C++ explicit operator bool() mit operator pointer-to-member(), die zu einigen Problemen und Ineffizienz führten. Jetzt wird diese unzulängliche Problemumgehung vollständig entfernt.
Zufallszahlen: uniform_int_distribution ist jetzt perfekt zufällig, und shuffle() wurde in <algorithm> implementiert, das direkt Uniform Random Number-Generatoren wie mersenne_twister akzeptiert.
Verhinderung überladener address-of-Operatoren: C++98/03 verbietet, dass ein Element eines STL-Containers seinen address-of-Operator überlädt. Dies erfolgt aber in Klassen wie CComPtr, sodass Hilfsklassen wie CAdapt erforderlich sind, um STL gegen solche Überladungen abzuschirmen. Während der Entwicklung von Visual C++ in Visual Studio 2010 haben STL-Änderungen bewirkt, dass überladene address-of-Operatoren in weiteren Situationen abgelehnt wurden. C++11 ändert die Anforderungen, damit überladene address-of-Operator möglich werden. C++11 und Visual C++ in Visual Studio 2010 stellen die Hilfsfunktion std::addressof() bereit, welche die tatsächliche Adresse eines Objekts auch bei einer Operatorüberladung abrufen kann. Bevor Visual C++ in Visual Studio 2010 freigegeben wurde, haben wir versucht, Vorkommen von "&elem" durch "std::addressof(elem)" zu ersetzen, was weiterhin geeignet ist. Visual C++ in Visual Studio 2012 ging noch weiter, sodass Klassen, die ihren address-of-Operator überladen, innerhalb der STL verwendbar sein sollten.
Visual C++ in Visual Studio 2012 ging in verschiedener Hinsicht über C++11 hinaus:
SCARY-Iteratoren: Obwohl vom C++11-Standard nicht gefordert, aber erlaubt, wurden SCARY-Iteratoren implementiert, wie in N2911 "Minimizing Dependencies within Generic Classes for Faster and Smaller Programs" und N2980 "SCARY Iterator Assignment and Initialization, Revision 1" beschrieben.
Dateisystem: Der <filesystem>-Header aus dem TR2-Antrag wurde hinzugefügt. Er bietet recursive_directory_iterator und weitere interessante Features. Bevor die Arbeit an TR2 eingestellt wurde, da C++0x sehr spät kam und sich zu C++11 entwickelt hat, wurde der Antrag aus 2006 von Boost.Filesystem V2 abgeleitet. Es wurde später zu Boost.Filesystem V3, was aber nicht in Visual C++ in Visual Studio 2012 implementiert ist.
Und eine wichtige Optimierung! Alle unsere Container sind jetzt entsprechend ihren aktuellen Darstellungen optimal klein. Dies bezieht sich auf die Containerobjekte selbst, nicht auf die darin referenzierten Inhalte. Beispielsweise enthält std::vector drei unformatierte Zeiger. In Visual C++ in Visual Studio 2010, im x86-Releasemodus, umfasste std::vector 16 Bytes. In Visual C++ in Visual Studio 2012 sind es 12 Bytes, eine optimale Größe. Dies ist schon beachtlich. Wenn ein Programm 100.000 Vektoren enthält, benötigt Visual C++ in Visual Studio 2012 400.000 Bytes weniger. Verringerte Speicherauslastung spart Platz und Zeit.
Dies wurde erreicht, weil leere Allokatoren und Komparatoren nicht mehr gespeichert werden, da std::allocator und std::less zustandslos sind. (Diese Optimierungen sind auch für benutzerdefinierte Allokatoren/Komparatoren aktiviert, solange sie zustandslos sind. Selbstverständlich kann die Speicherung von zustandsbehafteten Allokatoren/Komparatoren nicht vermieden werden; diese sind jedoch sehr selten).
Visual C++ in Visual Studio 2013 geht weiter über C++11 hinaus, um einige wichtige C++14-Bibliotheksfunktionen zu implementieren:
Transparente "Operatorfunktionselemente" less<>, greater<>, plus<>, multiplies<> usw.
make_unique<T>(args...) und make_unique<T[]>(n)
cbegin()/cend(), rbegin()/rend() und crbegin()/crend()-nicht-Memberfunktionen.
[go to top]
Siehe auch
Referenz
Bereichsbasiert für Anweisung (C++)
Konzepte
Neues über Visual C++ in Visual Studio 2013
Wichtige Änderungen in Visual C++
Weitere Ressourcen
Willkommen zurück bei C++ (Modern C++)