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

C++11-Kernsprachenfunktionen

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

Rvalue-Referenzen v0.1, v1.0, v2.0, v2.1, v3.0

v2.0

v2.1*

v2.1*

ref-Qualifizierer

Nein

Nein

Nein

Nicht statische Datenmemberinitialisierer

Nein

Nein

Ja

Variadic-Vorlagen v0.9, v1.0

Nein

Nein

Ja

Initialisierungslisten

Nein

Nein

Ja

static_assert

Ja

Ja

Ja

auto v0.9, v1.0

v1.0

v1.0

v1.0

Nachstehende Rückgabetypen

Ja

Ja

Ja

Lambdas v0.9, v1.0, v1.1

v1.0

v1.1

v1.1

decltype v1.0, v1.1

v1.0

v1.1**

v1.1

Öffnende spitze Klammern

Ja

Ja

Ja

Standardvorlagenargumente für Funktionsvorlagen

Nein

Nein

Ja

SFINAE für Ausdrücke

Nein

Nein

Nein

Aliasvorlagen

Nein

Nein

Ja

Extern-Vorlagen

Ja

Ja

Ja

nullptr

Ja

Ja

Ja

Stark typisierte Enumerationen

Partial

Ja

Ja

Vorwärts deklarierte Enumerationen

Nein

Ja

Ja

Attribute

Nein

Nein

Nein

constexpr

Nein

Nein

Nein

Ausrichtung

TR1

Partial

Partial

Delegierende Konstruktoren

Nein

Nein

Ja

Konstruktorvererbung

Nein

Nein

Nein

Explizite Konvertierungsoperatoren

Nein

Nein

Ja

char16_t/char32_t

Nein

Nein

Nein

Unicode-Zeichenfolgenliterale

Nein

Nein

Nein

Unformatierte Zeichenfolgenliterale

Nein

Nein

Ja

Universelle Zeichennamen in Literalen

Nein

Nein

Nein

Benutzerdefinierte Literale

Nein

Nein

Nein

Standardlayout und einfache Typen

Nein

Ja

Ja

Defaulted- und Deleted-Funktionen

Nein

Nein

Ja*

Erweiterte Friend-Deklarationen

Ja

Ja

Ja

Erweitertes sizeof

Nein

Nein

Nein

Inlinenamespaces

Nein

Nein

Nein

Uneingeschränkte Unions

Nein

Nein

Nein

Lokale und unbenannte Typen als Vorlagenargumente

Ja

Ja

Ja

Bereichsbasierte For-Schleife

Nein

Ja

Ja

override und final v0.8, v0.9, v1.0

Partial

Ja

Ja

Minimale GC-Unterstützung

Ja

Ja

Ja

noexcept

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

Neu formulierte Sequenzpunkte

Nicht zutreffend

Nicht zutreffend

Nicht zutreffend

Atomics

Nein

Ja

Ja

Starke compare_exchange-Operation

Nein

Ja

Ja

Bidirektionale Fences

Nein

Ja

Ja

Speichermodell

Nicht zutreffend

Nicht zutreffend

Nicht zutreffend

Datenabhängigkeits-Reihenfolge

Nein

Ja

Ja

Datenabhängigkeits-Reihenfolge: Funktionsannotation

Nein

Nein

Nein

exception_ptr

Ja

Ja

Ja

quick_exit

Nein

Nein

Nein

Atomics in Signalhandlern

Nein

Nein

Nein

Lokaler Threadspeicher

Partial

Partial

Partial

"Magische" static-Objekte

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

__func__

Partial

Partial

Partial

C99-Präprozessor

Partial

Partial

Partial

long long

Ja

Ja

Ja

Erweiterte Integer-Typen

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

Lambda-Ausdrücke in C++

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++)

C++-Sprachreferenz

C++-Standardbibliotheksreferenz

Visual C++-Team-Blog