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
Visual Studio 2010 |
Visual Studio 2012 |
Visual Studio 2013 |
|
---|---|---|---|
v2.0 |
v2.1* |
v2.1* |
|
No |
No |
No |
|
No |
No |
||
No |
No |
||
No |
No |
||
Sì |
Sì |
Sì |
|
v1.0 |
v1.0 |
v1.0 |
|
Sì |
Sì |
Sì |
|
v1.0 |
v1.1 |
v1.1 |
|
v1.0 |
v1.1** |
v1.1 |
|
Sì |
Sì |
Sì |
|
No |
No |
Sì |
|
No |
No |
No |
|
No |
No |
||
Sì |
Sì |
Sì |
|
Sì |
Sì |
Sì |
|
Partial |
Sì |
Sì |
|
No |
Sì |
Sì |
|
No |
No |
No |
|
No |
No |
No |
|
TR1 |
Partial |
Partial |
|
No |
No |
||
No |
No |
No |
|
No |
No |
Sì |
|
No |
No |
No |
|
No |
No |
No |
|
No |
No |
||
No |
No |
No |
|
No |
No |
No |
|
No |
Sì |
Sì |
|
No |
No |
||
Sì |
Sì |
Sì |
|
No |
No |
No |
|
No |
No |
No |
|
No |
No |
No |
|
Sì |
Sì |
Sì |
|
No |
Sì |
Sì |
|
Partial |
Sì |
Sì |
|
Sì |
Sì |
Sì |
|
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 |
---|---|---|---|
N/D |
N/D |
N/D |
|
No |
Sì |
Sì |
|
No |
Sì |
Sì |
|
No |
Sì |
Sì |
|
N/D |
N/D |
N/D |
|
No |
Sì |
Sì |
|
No |
No |
No |
|
Sì |
Sì |
Sì |
|
No |
No |
No |
|
No |
No |
No |
|
Partial |
Partial |
Partial |
|
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 |
---|---|---|---|
Partial |
Partial |
Partial |
|
Partial |
Partial |
Partial |
|
Sì |
Sì |
Sì |
|
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
Istruzione for basata su intervallo (C++)
Concetti
Novità relative a Visual C++ in Visual Studio 2013
Ultime modifiche in Visual C++
Altre risorse
Riferimenti del linguaggio C++