Es wird empfohlen, Visual Studio 2017 zu verwenden

Unterstützung für C++11/14/17-Funktionen (Modern C++)

 

Veröffentlicht: Juli 2016

Die neueste Dokumentation zu Visual Studio 2017 finden Sie unter Dokumentation zu Visual Studio 2017.

Dieser Artikel beschreibt C++11/14/17-Features in Visual C++.

Visual C++ implementiert den Großteil der Features in der C++11-Kernsprachenspezifikation sowie zahlreiche C++17-Bibliotheksfeatures und einige für C++17 vorgeschlagene Features. In der folgenden Tabelle sind die C++11/14/17-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

Features der C++11-KernspracheVisual Studio 2010Visual Studio 2012Visual Studio 2013Visual Studio 2015
rvalue-Referenzen v0.1, v1.0, v2.0, v2.1, v3.0v2.0v2.1*v2.1*v3.0
ref-QualifiziererNeinNeinNeinJa
Nicht statische DatenmemberinitialisiererNeinNeinJaJa
variadic-Vorlagen v0.9, v1.0NeinNeinJaJa
InitialisiererlistenNeinNeinJaJa
static_assertJaJaJaJa
auto v0.9, v1.0v1.0v1.0v1.0Ja
Nachstehende RückgabetypenJaJaJaJa
Lambdas v0.9, v1.0, v1.1v1.0v1.1v1.1Ja
decltype v1.0, v1.1v1.0v1.1**v1.1Ja
Öffnende spitze KlammerJaJaJaJa
Standardvorlagenargumente für FunktionsvorlagenNeinNeinJaJa
SFINAE für AusdrückeNeinNeinNeinNein
Alias-VorlagenNeinNeinJaJa
Extern-VorlagenJaJaJaJa
nullptrJaJaJaJa
Stark typisierte EnumerationenPartialJaJaJa
Vorwärts deklarierte EnumerationenNeinJaJaJa
AttributeNeinNeinNeinJa
constexprNeinNeinNeinJa
AusrichtungTR1PartialPartialJa
Delegierende KonstruktorenNeinNeinJaJa
KonstruktorvererbungNeinNeinNeinJa
Explizite KonvertierungsoperatorenNeinNeinJaJa
char16_t/char32_tNeinNeinNeinJa
Unicode-ZeichenfolgenliteraleNeinNeinNeinJa
Unformatierte ZeichenfolgenliteraleNeinNeinJaJa
Universelle Zeichennamen in LiteralenNeinNeinNeinJa
Benutzerdefinierte LiteraleNeinNeinNeinJa
Standardlayout- und einfache TypenNeinJaJaJa
Defaulted- und Deleted-FunktionenNeinNeinJa*Ja
Erweiterte Friend-DeklarationenJaJaJaJa
Erweitertes sizeofNeinNeinNeinJa
InlinenamespacesNeinNeinNeinJa
Uneingeschränkte UnionsNeinNeinNeinJa
Lokale und unbenannte Typen als VorlagenargumenteJaJaJaJa
Bereichsbasierte For-Loop-SchleifeNeinJaJaJa
override und final v0.8, v0.9, v1.0PartialJaJaJa
Minimale GC-UnterstützungJaJaJaJa
noexceptNeinNeinNeinJa

[In diesem Artikel]

Funktionstabelle für C++11-Kernsprachfunktionen: Nebenläufigkeit

Features der C++11-Kernsprache: NebenläufigkeitVisual Studio 2010Visual Studio 2012Visual Studio 2013Visual Studio 2015
Neu formulierte SequenzpunkteNicht zutreffendNicht zutreffendNicht zutreffendJa
AtomicsNeinJaJaJa
Starke compare_exchange-OperationNeinJaJaJa
Bidirektionale FencesNeinJaJaJa
SpeichermodellNicht zutreffendNicht zutreffendNicht zutreffendJa
Datenabhängigkeits-ReihenfolgeNeinJaJaJa
Datenabhängigkeits-Reihenfolge: FunktionsanmerkungNeinNeinNeinJa
exception_ptrJaJaJaJa
quick_exitNeinNeinNeinJa
Atomics in SignalhandlernNeinNeinNeinNein
Lokaler ThreadspeicherPartialPartialPartialJa
„Magische“ static-ObjekteNeinNeinNeinJa

[In diesem Artikel]

Features der C++11-Kernsprache: C99

Features der C++11-Kernsprache: C99Visual Studio 2010Visual Studio 2012Visual Studio 2013Visual Studio 2015
__func__PartialPartialPartialJa
C99-PräprozessorPartialPartialPartialPartial
long longJaJaJaJa
Erweiterte Integer-TypenNicht zutreffendNicht zutreffendNicht zutreffendNicht zutreffend

[In diesem Artikel]

Features der C++14-Kernsprache

FunktionVisual Studio 2013Visual Studio 2015
Optimierte Formulierungen für kontextbezogene KonvertierungenJaJa
Binäre LiteraleNeinJa
Rückagebetypen „auto“ und „decltype(auto)“NeinJa
init-capturesNeinJa
Generische Lambda-AusdrückeNeinJa
VariablenvorlagenNeinNein
Erweiterte constexprNeinNein
NSDMIs für AggregateNeinNein
Zuordnungen vermeiden/zusammenführenNeinNein
[[veraltet]]-AttributeNeinNein
Zuordnung nach GrößeNeinJa
ZahlentrennzeichenNeinJa

Vorgeschlagene C++17-Kernsprachenfunktionen

FunktionVisual Studio 2013Visual Studio 2015
Neue Regeln für „auto“ mit „braced-init-lists“NeinNein
Knappes statisches „assert“NeinNein
typename in Vorlagen-VorlagenparameterNeinNein
Entfernen von TrigraphenJaJa
Geschachtelte NamespacedefinitionenNeinNein
N4259 std::uncaught_exceptions()NeinNein
N4261 Qualifikationskonvertierungen behebenNeinNein
N4266 Attribute für Namespaces und EnumeratorenNeinNein
N4267 u8-ZeichenliteraleNeinNein
N4268 Mehr Nicht-Typen-Vorlagenargumente zulässigNeinNein
N4295 Fold-AusdrückeNeinNein
await/resumeNeinJa

rvalue-Referenzen

System_CAPS_ICON_note.jpg 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. Dies ist in Visual Studio 2015 implementiert.

[In diesem Artikel]

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. Dies erzeugt Lambdas Version „1.1“, die jetzt vollständig unterstützt wird. 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.)

[In diesem Artikel]

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.

[In diesem Artikel]

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.

[In diesem Artikel]

Ausrichtung

Die Kernsprachenschlüsselwörter alignas/alignof aus dem alignment-Vorschlag, der in das Arbeitspapier gewählt wurde, sind in Visual Studio 2015 implementiert. 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.

[In diesem Artikel]

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 dem 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; };  
  

System_CAPS_ICON_note.jpg Hinweis

Weitere wichtige Änderungen finden Sie unter Wichtige Änderungen in Visual C++ 2015.

[In diesem Artikel]

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 Funktionen.

[In diesem Artikel]

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. Anschließend 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.

[In diesem Artikel]

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>.

[In diesem Artikel]

C99 __func__ und Präprozessorregeln

In der Tabelle Features der C++11-Kernsprache: 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.

[In diesem Artikel]

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 werden bereitgestellt. Weitere Informationen finden Sie im Abschnitt zur Unterstützung der 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. Dies hat sich später zu Boost.Filesystem V3 entwickelt, das in Visual Studio 2015 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 implementiert einige wichtige C ++ 14-Bibliotheksfunktionen:

  • 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.

[In diesem Artikel]

Willkommen zurück bei C++
C++-Sprachreferenz
Lambda-Ausdrücke
Bereichsbasiert für Anweisung (C++)
C++-Standardbibliothek
Visual C++-Team-Blog
Neues bei Visual C++
Wichtige Änderungen in Visual C++ 2015

Anzeigen: