Condividi tramite


Supporto delle funzionalità C++11 (C++ moderno)

Questo articolo descrive le funzionalità di C++11 in Visual C++.

Contenuto dell'articolo

  • 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

Elenco delle funzionalità di C++11

In Visual C++ in Visual Studio 2010 sono state implementate molte delle funzionalità della specifica del linguaggio core C++11, mentre in Visual C++ in Visual Studio 2012 sono state aggiunte altre funzionalità. Visual C++ in Visual Studio 2013 amplia ulteriormente la copertura aggiungendo il supporto di alcune funzionalità della libreria C++14. Nella tabella seguente sono elencate le funzionalità del linguaggio core C++11 con il relativo stato di implementazione in Visual C++ in Visual Studio 2010, in Visual C++ in Visual Studio 2012 e in Visual C++ in Visual Studio 2013.

Tabella delle funzionalità del linguaggio core C++11

Funzionalità del linguaggio core C++11

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

Riferimenti rvalue v0.1, v1.0, v2.0, v2.1, v3.0

v2.0

v2.1*

v2.1*

Qualificatori ref

No

No

No

Inizializzatori di membri dati non statici

No

No

Modelli Variadic v0.9, v1.0

No

No

Elenchi di inizializzatori

No

No

static_assert

auto v0.9, v1.0

v1.0

v1.0

v1.0

Tipi restituiti finali

Lambda v0.9, v1.0, v1.1

v1.0

v1.1

v1.1

decltype v1.0, v1.1

v1.0

v1.1**

v1.1

Parentesi angolari chiuse

Argomenti di modello predefiniti per modelli di funzione

No

No

Espressione SFINAE

No

No

No

Modelli di alias

No

No

Modelli Extern

nullptr

Enumerazioni fortemente tipizzate

Partial

Enumerazioni dichiarate con prototipo

No

Attributi

No

No

No

constexpr

No

No

No

Allineamento

TR1

Partial

Partial

Costruttori deleganti

No

No

Costruttori ereditanti

No

No

No

Operatori di conversione esplicita

No

No

char16_t/char32_t

No

No

No

Valori letterali stringa Unicode

No

No

No

Valori letterali stringa non elaborati

No

No

Nomi di caratteri universali in valori letterali

No

No

No

Valori letterali definiti dall'utente

No

No

No

Tipi semplici e tipi layout standard

No

Funzioni impostate come predefinite e funzioni eliminate

No

No

Sì*

Dichiarazioni Friend estese

sizeof esteso

No

No

No

Spazi dei nomi inline

No

No

No

Unioni senza restrizioni

No

No

No

Tipi locali e senza nome come argomenti di modello

Ciclo for basato su intervallo

No

Override e finale v0.8, v0.9, v1.0

Partial

Supporto GC minimo

noexcept

No

No

No

[go to top]

Tabella delle funzionalità del linguaggio core C++11: concorrenza

Funzionalità del linguaggio core C++11: concorrenza

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

Punti di sequenza riscritti

N/D

N/D

N/D

Tipi atomici

No

Confronto e scambio avanzati

No

Recinti bidirezionali

No

Modello di memoria

N/D

N/D

N/D

Ordinamento di dipendenze dei dati

No

Ordinamento di dipendenze di dati: annotazione di funzione

No

No

No

exception_ptr

quick_exit

No

No

No

Tipi atomici in gestori di segnali

No

No

No

Archiviazione locale di thread

Partial

Partial

Partial

Elementi statici utili

No

No

No

[go to top]

Funzionalità del linguaggio core C++11: C99

Funzionalità del linguaggio core C++11: C99

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

__func__

Partial

Partial

Partial

Preprocessore C99

Partial

Partial

Partial

long long

Tipi Integer estesi

N/D

N/D

N/D

[go to top]

Guida alle tabelle delle funzionalità

Riferimenti rvalue

Nota

Le designazioni di versione (v0.1, v1.0, v2.0, v2.1, v3.0) usate nelle descrizioni seguenti hanno il solo scopo di mostrare l'evoluzione del linguaggio C++11.Lo standard stesso non le utilizza.

N1610 "Informazioni sull'inizializzazione degli oggetti classe per rvalue" è un primo tentativo di abilitare la semantica di spostamento senza riferimenti rvalue. Ai fini di questa discussione, si parlerà di "riferimenti rvalue v0.1". È stato sostituito da "Riferimenti rvalue v1.0". I "riferimenti rvalue v2.0", ovvero il concetto su cui si basa il lavoro in Visual C++ in Visual Studio 2010, impediscono l'associazione tra i riferimenti rvalue e i riferimenti lvalue, risolvendo quindi un problema di sicurezza molto importante. " I "riferimenti rvalue v2.1" perfezionano questa regola. Prendere in considerazione vector<string>::push_back(), con gli overload push_back(const string&) e push_back(string&&)e la chiamata a v.push_back("strval"). L'espressione "strval" è un valore letterale stringa e un lvalue. (Altri valori letterali, ad esempio l'intero 1729, sono rvalue, ma i valori letterali stringa sono speciali perché rappresentano matrici). Le regole dei "riferimenti rvalue v2.0" stabiliscono che string&& non può essere associato a "strval" perché "strval" è un lvalue, di conseguenza push_back(const string&) è l'unico overload possibile. Le conseguenze sarebbero la creazione di un oggetto std::stringtemporaneo, la sua copia nel vettore e infine l'eliminazione dell'oggetto std::string temporaneo, una procedura poco efficiente. Le regole dei "riferimenti rvalue v2.1" riconoscono che l'associazione di string&& a "strval" creerebbe un oggetto std::stringtemporaneo rvalue. Di conseguenza, sono possibili sia push_back(const string&) sia push_back(string&&), ma push_back(string&&) è preferibile. Viene costruito un oggetto std::string temporaneo, che verrà spostato nel vettore. Questa procedura è più efficiente.

I "riferimenti rvalue v3.0" aggiungono nuove regole per generare automaticamente i costruttori di spostamento e gli operatori di assegnazione di spostamento in determinate condizioni. Tuttavia, per vincoli di risorse e di tempo, questo processo non è stato implementato in Visual C++ in Visual Studio 2013.

[go to top]

Lambda

Dopo l'inserimento delle funzioni lambda nel documento di lavoro (versione "0.9") e l'aggiunta delle espressioni lambda modificabili (versione "1.0"), il comitato di standardizzazione ha revisionato l'espressione. Ciò ha permesso di ottenere lambda versione "1.1", per cui è ora disponibile supporto completo. La definizione delle espressioni lambda v1.1 chiarisce cosa dovrebbe accadere in casi estremi come il riferimento a membri statici o a espressioni lambda annidate. In questo modo, si risolvono i problemi generati dalle espressioni lambda complesse. Le espressioni lambda sono ora convertibili in puntatori a funzione. Questo non è presente nella definizione N2927, ma è comunque inteso come parte delle espressioni lambda v1.1. C++11 5.1.2 [expr.prim.lambda]/6 presenta la seguente descrizione: "Il tipo di chiusura di una lambda-expression con nessuna lambda-capture dispone di una funzione di conversione const non esplicita non virtuale pubblica per puntare alla funzione con lo stesso parametro e gli stessi tipi restituiti dell'operatore di chiamata di funzione del tipo di chiusura. Il valore restituito dalla funzione di conversione sarà l'indirizzo di una funzione che, quando richiamata, avrà lo stesso effetto di quando viene richiamato l'operatore di chiamata di funzione del tipo di chiusura". (L'implementazione di Visual C++ in Visual Studio 2012 è ancora migliore perché rende le espressioni lambda indipendenti dallo stato convertibili in puntatori funzione che utilizzano convenzioni di chiamata arbitrarie. Questo è importante quando si usano API che si aspettano elementi come i puntatori funzione __stdcall).

[go to top]

decltype

Dopo l'inserimento di decltype nel documento di lavoro (versione 1.0), è stata apportata una piccola ma importante correzione (versione 1.1). Tale modifica riveste molta importanza per i programmatori che lavorano su STL e Boost.

[go to top]

Enumerazioni fortemente tipizzate/dichiarate con prototipo

Le enumerazioni fortemente tipizzate sono in parte supportate in Visual C++ in Visual Studio 2010 (in particolare, la parte sui tipi sottostanti specificati in modo esplicito). Ora sono completamente implementate in Visual Studio, così come la semantica C++11 per le enumerazioni dichiarate con prototipo.

[go to top]

Allineamento

Le parole chiave del linguaggio core alignas/alignof contenute nella proposta di allineamento inserita nel documento di lavoro non sono implementate. Visual C++ in Visual Studio 2010 dispone di aligned_storage da TR1. In Visual C++ in Visual Studio 2012 sono state aggiunte le parole chiave aligned_union e std::align() alla libreria standard e sono stati corretti alcuni problemi significativi in Visual C++ in Visual Studio 2013.

[go to top]

Tipi semplici e tipi layout standard

Le modifiche esposte da N2342 "POD riconfigurati; Risoluzione del problema principale 568 (Revisione 5)" sono le aggiunte di is_trivial e is_standard_layout della libreria di modelli standard <type_traits>. (N2342 ha rielaborato molte delle definizioni del linguaggio core, ma non sono state necessarie modifiche del compilatore). Questi tratti dei tipi sono disponibili in Visual C++ in Visual Studio 2010, ma duplicano semplicemente is_pod. Ecco perché nella tabella riportata sopra in questo documento il supporto viene indicato come non disponibile. Sono ora sono basati sugli hook del compilatore progettati per fornire risposte precise.

Il common_type<> di STL ha ricevuto una correzione da molto tempo auspicata in Visual C++ in Visual Studio 2013. La specifica C++11 per common_type<> presenta delle conseguenze impreviste e indesiderate, in particolare induce common_type<int, int>::type a restituire int&&. Visual C++ in Visual Studio 2013 implementa quindi la Proposta per risolvere il problema 2141 del gruppo di lavoro di libreria, che fa sì che common_type<int, int>::type restituisca int.

Come effetto collaterale di questa modifica, il case di identità non funziona più (common_type<T> non restituisce sempre il tipo T). Ciò è conforme alla Proposta, ma interrompe il codice basato sul comportamento precedente.

Se è necessario un tratto di tipo identità, non utilizzare l'elemento std::identity non standard definito in <type_traits>, perché non funzionerà con <void>. Diversamente, implementare un tratto di tipo di identità per le proprie esigenze. Di seguito è riportato un esempio:

template <typename T> struct Identity {
    typedef T type;
};

Nota

Per altre modifiche importanti, vedere Ultime modifiche in Visual C++.

[go to top]

Funzioni impostate come predefinite e funzioni eliminate

Ora sono supportate, ma con questa eccezione: per le funzioni impostate come predefinite, l'utilizzo di =default per richiedere costruttori di spostamento per i membri e operatori di assegnazione di spostamento non è supportato. Le copie e gli spostamenti non interagiscono con precisione come indicato dallo standard, ad esempio l'eliminazione degli spostamenti dovrebbe anche eliminare le copie, ma questo non avviene in Visual C++ in Visual Studio 2013.

Per informazioni sull'uso delle funzioni impostate come predefinite e sulle funzioni eliminate, vedere Definizioni di funzioni C++.

[go to top]

override e finale

L'evoluzione è avvenuta rapidamente ma con qualche complicazione. Originariamente, nella versione 0.8, erano disponibili gli attributi [[override]], [[hiding]] e [[base_check]]. Nella versione 0.9 gli attributi sono stati eliminati e sostituiti con parole chiave contestuali. Infine, nella versione 1.0 sono stati ridotti a "final" nelle classi e "override" e "final" nelle funzioni. Si tratta di un'estensione verso l'alto perché Visual C++ in Visual Studio 2010 supporta già questa sintassi di "override" sulle funzioni e dispone di una semantica abbastanza simile a quella di C++11". Anche "final" è supportato, ma con la formulazione diversa "sealed". L'ortografia e la semantica standard di "override" e "final" sono ora completamente supportate. Per altre informazioni, vedere Identificatore override e Identificatore final.

[go to top]

Elementi atomici e altro

Tipi atomici, Confronto e scambio avanzati, Recinti bidirezionali e Ordinamento di dipendenze di dati: annotazione di funzione specificano il sistema della libreria standard, che è ora implementato.

Intestazioni STL correlate: <atomic>, <chrono>, <condition_variable>, <future>, <mutex>, <ratio>, <scoped_allocator> e <thread>.

[go to top]

__func__ e regole di preprocessore C99

Nella tabella Core Language Feature Table: C99 è elencata l'implementazione "parziale" per due elementi. Per l'identificatore predefinito __func__ è indicato "Parziale" poiché è fornito supporto per le estensioni non standard __FUNCDNAME__, __FUNCSIG__ e __FUNCTION__. Per altre informazioni, vedere Macro predefinite. Per le regole di preprocessore C99 è indicato "Parziale" poiché sono supportate le macro variadic. Per altre informazioni, vedere Macro variadic.

[go to top]

Funzionalità della libreria standard

Riguarda il linguaggio core. Come per la libreria standard C++11, non è disponibile una vera e propria tabella di confronto delle funzionalità, anche se in Visual C++ in Visual Studio 2012 è stata implementata con due eccezioni. Innanzitutto, quando una funzionalità della libreria dipende da funzionalità mancanti nel compilatore, viene simulata, ad esempio vengono simulati i modelli variadic per make_shared<T>(), oppure non viene implementata. Esistono solo alcuni casi, in particolare <initializer_list>, che ora sono completamente implementati in Visual C++ in Visual Studio 2013. Con poche eccezioni, C99 è stato implementato nelle intestazioni del wrapper C++ e Visual C++ in Visual Studio 2013 fornite. Per altre informazioni, vedere il post di blog relativo al supporto per la libreria C99 in Visual Studio 2013.

Di seguito è riportato un elenco parziale delle modifiche in Visual C++ in Visual Studio 2012 e Visual C++ in Visual Studio 2013:

Ubicazione: come richiesto da C++11, emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() sono implementati in tutti i contenitori di numeri "arbitrari" di argomenti (vedere la sezione "Variadics simulate"). Ad esempio, vector<T> presenta "template <typename... Args> void emplace_back(Args&&... args)", che costruisce direttamente un elemento di tipo T nella parte posteriore del vettore da un numero arbitrario di argomenti arbitrari, inoltrati perfettamente. Questo processo potrebbe risultare più efficace rispetto a push_back(T&&), il quale comporterebbe una costruzione e una distruzione di spostamento aggiuntive.

Variadics: in Visual C++ in Visual Studio 2012 è disponibile uno schema per la simulazione dei modelli di variadic. In Visual C++ in Visual Studio 2013, le simulazioni non sono più disponibili e le variadics sono implementate completamente. Se il codice si basa sul comportamento precedente di variadics simulate, è necessario correggerlo. Tuttavia, il passaggio a modelli di variadic reali ha contribuito a migliorare i tempi di compilazione e a ridurre il consumo di memoria del compilatore.

Operatori di conversione espliciti: nel linguaggio core gli operatori di conversione espliciti rappresentano una funzionalità generale, ad esempio è possibile disporre di explicit operator MyClass(). Tuttavia, la libreria standard utilizza attualmente un'unica forma, explicit operator bool(), che rende le classi verificabili in modo booleano. ("operator bool()" normale è notoriamente pericoloso). In precedenza, Visual C++ simulava explicit operator bool() con operator pointer-to-member(), cosa che ha creato diversi problemi e piccole inefficienze. La soluzione alternativa che prevedeva l'utilizzo di un "valore booleano fittizio" è stata completamente rimossa.

Casualità: uniform_int_distribution è ora completamente imparziale e shuffle() viene implementato in <algorithm>, che accetta direttamente i generatori di numeri casuali uniformi come mersenne_twister.

Resistenza agli operatori address-of in overload: le versioni C++98/03 impediscono a un elemento di un contenitore STL di eseguire l'overload del proprio operatore address-of. Questo è ciò che fanno le classi come CComPtr, per cui si sono rese necessarie le classi di supporto come CAdapt per proteggere STL da tali overload. Durante lo sviluppo di Visual C++ in Visual Studio 2010, le modifiche a STL causavano il rifiuto degli operatori address-of sottoposti a overload in più situazioni. C++11 ha modificato i requisiti per rendere accettabili gli operatori address- of sottoposti a overload. In C++11 e Visual C++ in Visual Studio 2010 viene fornita la funzione di supporto std::addressof() che può ottenere l'indirizzo effettivo di un oggetto indipendentemente dall'overload degli operatori. Prima del rilascio di Visual C++ in Visual Studio 2010, è stato effettuato il tentativo di sostituire le occorrenze di "&elem" con "std::addressof(elem)", che offre una resistenza appropriata. Visual C++ in Visual Studio 2012 è andato oltre, in modo che le classi che sono in rapporto di overload con il rispettivo operatore address-of possano essere usate in STL.

In Visual C++ in Visual Studio 2012 si è andati oltre C++11 in diversi modi:

Iteratori SCARY: come permesso, ma non richiesto dal linguaggio C++11 standard, gli iteratori SCARY sono stati implementati, come descritto nell'articolo N2911 relativo alla riduzione delle dipendenze in classi generiche per lo sviluppo di programmi di dimensioni più piccole e più veloci e nell'articolo N2980 relativo all'inizializzazione e all'assegnazione dell'iteratore SCARY, revisione 235115.

Filesystem: l'intestazione <filesystem> dalla proposta TR2 è stata aggiunta. Tale intestazione rende disponibili recursive_directory_iterator e altre interessanti funzionalità. Prima che il lavoro su TR2 fosse bloccato dato il ritardo di C++0x e il passaggio a C++11, la proposta 2006 fu derivata da Boost.Filesystem V2. In seguito si è verificato il passaggio a Boost.Filesystem V3, ma senza l'implementazione in Visual C++ in Visual Studio 2012.

E un'ottimizzazione molto importante. Tutti i contenitori presentano ora dimensioni ottimali, date le relative rappresentazioni. Questo fa riferimento agli oggetti contenitore stessi, non al relativo contenuto puntato. Ad esempio, std::vector contiene tre puntatori non elaborati. In Visual C++ in Visual Studio 2010, la modalità di rilascio x86 std::vector è a 16 byte. In Visual C++ in Visual Studio 2012 è a 12 byte, ovvero dimensioni ridotte ottimali. Si tratta di un grande vantaggio: se nel programma sono presenti 100.000 vettori, Visual C++ in Visual Studio 2012 consente di risparmiare 400.000 byte. Un utilizzo ridotto della memoria consente di risparmiare spazio e tempo.

Questo risultato è stato ottenuto evitando l'archiviazione di allocatori e comparatori vuoti, perché std::allocator e std::less sono indipendenti dallo stato. (Queste ottimizzazioni sono possibili anche per gli allocatori/comparatori personalizzati, purché siano indipendenti dallo stato. Ovviamente, non è possibile evitare l'archiviazione di allocatori/comparatori dipendenti dallo stato, ma questi sono molto rari).

Visual C++ in Visual Studio 2013 fa ancora meglio di C++11 perché implementa alcune funzionalità chiave della libreria C++14:

  • "Funtori di operatori trasparenti" less<>, greater<>, plus<>, multiplies<> e così via.

  • make_unique<T>(args...) e make_unique<T[]>(n)

  • Funzioni non membro cbegin()/cend(), rbegin()/rend() e crbegin()crend().

[go to top]

Vedere anche

Riferimenti

Espressioni lambda in C++

Istruzione for basata su intervallo (C++)

Concetti

Novità relative a Visual C++ in Visual Studio 2013

Ultime modifiche in Visual C++

Altre risorse

C++ (C++ moderno)

Riferimenti del linguaggio C++

Riferimento per la libreria standard C++

Blog del team di Visual C++