Visual C++: novità dalla versione 2003 alla 2015Visual C++ What's New 2003 through 2015

Nota Per informazioni su Visual Studio 2017, vedere Novità di Visual C++ in Visual Studio 2017 e Miglioramenti della conformità di Visual C++ in Visual Studio 2017.Note For information about Visual Studio 2017, see What's new for Visual C++ in Visual Studio 2017 and Conformance Improvements in Visual C++ in Visual Studio 2017.

In Visual C++ 2015 e versioni successive i miglioramenti apportati in modo costante alla conformità del compilatore possono talvolta modificare il modo in cui il compilatore riconosce il codice sorgente esistente.In Visual C++ 2015 and later, ongoing improvements to compiler conformance can sometimes change how the compiler understands your existing source code. In questo caso, si possono riscontrare errori nuovi o diversi durante la compilazione o addirittura differenze di comportamento nel codice che apparentemente in precedenza veniva compilato ed eseguito correttamente.When this happens, you might encounter new or different errors during your build, or even behavioral differences in code that previously built and seemed to run correctly.

Fortunatamente, queste differenze hanno poco o nessun impatto sulla maggior parte del codice sorgente e quando è necessario usare codice sorgente o altre modifiche per risolvere queste differenze, le correzioni sono in genere minime e semplici.Fortunately, these differences have little or no impact on most of your source code and when source code or other changes are needed to address these differences, fixes are usually small and straight-forward. Sono stati inclusi numerosi esempi di codice sorgente in precedenza accettabile per cui potevano essere necessarie modifiche (prima) e di correzioni da apportare per risolvere i problemi (dopo).We've included many examples of previously-acceptable source code that might need to be changed (before) and the fixes to correct them (after).

Benché queste differenze possano influire sul codice sorgente o altri elementi di compilazione, non influiscono sulla compatibilità binaria tra gli aggiornamenti alle versioni di Visual C++.Although these differences can affect your source code or other build artifacts, they don't affect binary compatibility between updates to Visual C++ versions. Una modifica sostanziale, molto più drastica, può influire sulla compatibilità binaria, ma le interruzioni della compatibilità binaria si verificano solo tra le versioni principali di Visual C++.A more-severe kind of change, the breaking change can affect binary compatibility, but these kinds of binary compatibility breaks only occur between major versions of Visual C++. Ad esempio tra Visual C++ 2013 e Visual C++ 2015.For example, between Visual C++ 2013 and Visual C++ 2015. Per informazioni sulle modifiche sostanziali apportate tra Visual C++ 2013 e Visual C++ 2015, vedere Cronologia delle modifiche di Visual C++ dal 2003 al 2015.For information on the breaking changes that occurred between Visual C++ 2013 and Visual C++ 2015, see Visual C++ change history 2003 - 2015.

Miglioramenti della conformità in Visual C++ 2015 Conformance Improvements in Visual C++ 2015

  • /Zc:forScope- option/Zc:forScope- option

    L'opzione del compilatore /Zc:forScope- è deprecata e verrà rimossa in una versione futura.The compiler option /Zc:forScope- is deprecated and will be removed in a future release.

    Command line warning  D9035: option 'Zc:forScope-' has been deprecated and will be removed in a future release  
    

    L'opzione in genere è stata usata per consentire codice non standard che usa variabili di ciclo dopo il punto in cui, in base allo standard, dovrebbero essere uscite dall'ambito.The option was usually used in order to allow nonstandard code that uses loop variables after the point where, according to the standard, they should have gone out of scope. È necessaria solo quando si esegue la compilazione con l'opzione /Za, poiché è sempre consentito l'utilizzo di una variabile di ciclo dopo la fine del ciclo senza /Za.It was only necessary when you are compiling with the /Za option, since without /Za, using a for loop variable after the end of the loop is always allowed. Se non è rilevante la conformità agli standard (ad esempio, se il codice non è destinato a essere portabile in altri compilatori), è possibile disattivare l'opzione /Za (o impostare la proprietà Disabilita estensioni linguaggio su No).If you don't care about standards conformance (for example, if your code isn't meant to portable to other compilers), you could turn off the /Za option (or set the Disable Language Extensions property to No). Se si vuole scrivere codice portabile, conforme agli standard, è necessario riscrivere il codice affinché sia conforme allo standard spostando la dichiarazione di tali variabili in un punto esterno al ciclo.If you do care about writing portable, standards-compliant code, you should rewrite your code so that it conforms to the standard by moving the declaration of such variables to a point outside the loop.

    // zc_forScope.cpp  
    // compile with: /Zc:forScope- /Za  
    // C2065 expected  
    int main() {  
       // Uncomment the following line to resolve.  
       // int i;  
       for (int i =0; i < 1; i++)  
          ;  
       i = 20;   // i has already gone out of scope under /Za  
    }  
    
  • /Zg (opzione del compilatore)/Zg compiler option

    L'opzione del compilatore /Zg (Genera i prototipi delle funzioni) non è più disponibile.The /Zg compiler option (Generate Function Prototypes) is no longer available. Questa opzione del compilatore è stata precedentemente deprecata.This compiler option was previously deprecated.

  • Non è più possibile eseguire unit test con C++/CLI dalla riga di comando con mstest.exe.You can no longer run unit tests with C++/CLI from the command-line with mstest.exe. Usare invece vstest.console.exe.Instead, use vstest.console.exe. Vedere Opzioni della riga di comando di VSTest.Console.exe.See VSTest.Console.exe command-line options.

  • mutable (parola chiave)mutable keyword

    L'identificatore di classi di archiviazione mutable non è più consentito in posizioni dove in precedenza eseguiva compilazioni senza errori.The mutable storage class specifier is no longer allowed in places where previously it compiled without error. Ora il compilatore genera l'errore C2071 (classe di archiviazione non valida).Now, the compiler gives error C2071 (illegal storage class). In base allo standard, l'identificatore modificabile può essere applicato solo ai nomi dei membri di dati della classe, non può essere applicato ai nomi dichiarati const o statici e non può essere applicato ai membri di riferimento.According to the standard, the mutable specifier can be applied only to names of class data members, and cannot be applied to names declared const or static, and cannot be applied to reference members.

    Si consideri il codice di esempio seguente:For example, consider the following code:

    struct S {  
        mutable int &r;  
    };  
    

    Nelle versioni precedenti del compilatore Visual C++ questa situazione è accettabile, ma ora il compilatore genera l'errore seguente:Previous versions of the Visual C++ compiler accepted this, but now the compiler gives the following error:

    error C2071: 'S::r': illegal storage class  
    

    Per correggere l'errore, rimuovere semplicemente la parola chiave mutable ridondante.To fix the error, simply remove the redundant mutable keyword.

  • char_16_t e char32_tchar_16_t and char32_t

    Non è possibile usare char16_t o char32_t come alias di un typedef, poiché questi tipi ora vengono considerati come incorporati.You can no longer use char16_t or char32_t as aliases in a typedef, because these types are now treated as built-in. Per gli utenti e gli autori di libreria era comune definire char16_t e char32_t come alias rispettivamente di uint16_t e uint32_t.It was common for users and library authors to define char16_t and char32_t as aliases of uint16_t and uint32_t, respectively.

    #include <cstdint>  
    
    typedef uint16_t char16_t; //C2628  
    typedef uint32_t char32_t; //C2628  
    
    int main(int argc, char* argv[])  
    {  
    uint16_t x = 1; uint32_t y = 2;  
    char16_t a = x;   
    char32_t b = y;   
    return 0;  
    }  
    

    Per aggiornare il codice, rimuovere le dichiarazioni typedef e rinominare tutti gli identificatori che sono in conflitto con questi nomi.To update your code, remove the typedef declarations and rename any other identifiers that collide with these names.

  • Parametri di modello non di tipoNon-type template parameters

    Determinato codice che prevede parametri di modello non di tipo viene ora verificato correttamente per la compatibilità del tipo quando vengono forniti gli argomenti di modello espliciti.Certain code that involves non-type template parameters is now correctly checked for type compatibility when you provide explicit template arguments. Ad esempio, il seguente codice veniva compilato senza errori nelle versioni precedenti di Visual C++.For example, the following code compiled without error in previous versions of Visual C++.

    struct S1  
    {  
    void f(int);  
    void f(int, int);  
    };  
    
    struct S2  
    {  
    template <class C, void (C::*Function)(int) const> void f() {}  
    };  
    
    void f()  
    {  
    S2 s2;  
    s2.f<S1, &S1::f>();  
    }  
    

    Il compilatore corrente restituisce correttamente un errore, perché il tipo di parametro di modello non corrisponde all'argomento di modello (il parametro è un puntatore a un membro const, ma la funzione f è non const):The current compiler correctly gives an error, because the template parameter type doesn't match the template argument (the parameter is a pointer to a const member, but the function f is non-const):

    error C2893: Failed to specialize function template 'void S2::f(void)'note: With the following template arguments:note: 'C=S1'note: 'Function=S1::f'  
    

    Per risolvere questo errore nel codice, verificare che il tipo di argomento del modello usato corrisponda al tipo dichiarato del parametro di modello.To address this error in your code, make sure that the type of the template argument you use matches the declared type of the template parameter.

  • __declspec(align)__declspec(align)

    Il compilatore non accetta più __declspec(align) sulle funzioni.The compiler no longer accepts __declspec(align) on functions. È sempre stato ignorato, ma ora genera un errore del compilatore.This was always ignored, but now it produces a compiler error.

    error C3323: 'alignas' and '__declspec(align)' are not allowed on function declarations  
    

    Per risolvere questo problema, rimuovere __declspec(align) dalla dichiarazione di funzione.To fix this problem, remove __declspec(align) from the function declaration. Dal momento che non ha avuto effetto, la rimozione non comporta alcuna modifica.Since it had no effect, removing it does not change anything.

  • Gestione delle eccezioniException handling

    Sono state apportate alcune modifiche alla gestione delle eccezioni.There are a couple of changes to exception handling. In primo luogo, gli oggetti eccezione devono poter essere copiati o spostati.First, exception objects have to be either copyable or movable. Il codice seguente veniva compilato in --- --- Visual C++ in Visual Studio 2013Visual C++ in Visual Studio 2013, ma non viene compilato in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015:The following code compiled in --- --- Visual C++ in Visual Studio 2013Visual C++ in Visual Studio 2013, but does not compile in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015:

    struct S {  
    public:  
        S();  
    private:  
        S(const S &);  
    };  
    
    int main()  
    {  
        throw S(); // error  
    }  
    

    Il problema è che il costruttore di copia è privato e quindi l'oggetto non può essere copiato, come accade durante il normale funzionamento di gestione di un'eccezione.The problem is that the copy constructor is private, so the object cannot be copied as happens in the normal course of handling an exception. Lo stesso vale quando il costruttore di copia viene dichiarato explicit.The same applies when the copy constructor is declared explicit.

    struct S {  
        S();  
        explicit S(const S &);  
    };  
    
    int main()  
    {  
        throw S(); // error  
    }  
    

    Per aggiornare il codice, verificare che il costruttore di copia per l'oggetto eccezione sia pubblico e non sia contrassegnato come explicit.To update your code, make sure that the copy constructor for your exception object is public and not marked explicit.

    L'individuazione di un'eccezione in base al valore richiede anche che sia possibile copiare l'oggetto eccezione.Catching an exception by value also requires the exception object to be copyable. Il codice seguente veniva compilato in --- --- Visual C++ in Visual Studio 2013Visual C++ in Visual Studio 2013, ma non viene compilato in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015:The following code compiled in --- --- Visual C++ in Visual Studio 2013Visual C++ in Visual Studio 2013, but does not compile in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015:

    struct B {  
    public:  
        B();  
    private:  
        B(const B &);  
    };  
    
    struct D : public B {  
    };  
    
    int main()  
    {  
        try  
        {  
        }  
        catch (D d) // error  
        {  
        }  
    }  
    

    Per risolvere questo problema, è possibile modificare il tipo di parametro per catch in un riferimento.You can fix this issue by changing the parameter type for the catch to a reference.

    catch(D& d)  
    {  
    }  
    
  • Valori letterali stringa seguiti da macroString literals followed by macros

    Il compilatore supporta ora i valori letterali definiti dall'utente.The compiler now supports user defined literals. Di conseguenza, i valori letterali stringa seguiti da macro senza eventuali spazi intermedi vengono interpretati come valori letterali definiti dall'utente, che potrebbero produrre errori o risultati imprevisti.As a consequence, string literals followed by macros without any intervening whitespace are interpreted as user-defined literals, which might produce errors or unexpected results. Nei compilatori precedenti, ad esempio, il codice seguente veniva compilato correttamente:For example, in previous compilers the following code compiled successfully:

    #define _x "there"  
    char* func() {  
        return "hello"_x;  
    }  
    int main()  
    {  
        char * p = func();  
        return 0;  
    }  
    

    Il compilatore lo interpretava come un valore letterale stringa "hello" seguito da una macro, espansa in "there", e quindi i due valori letterali stringa venivano concatenati in uno.The compiler interpreted this as a string literal "hello" followed by a macro, which is expanded "there", and then the two string literals were concatenated into one. In --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015 il compilatore lo interpreta come un valore letterale definito dall'utente, ma poiché non esiste alcun valore letterale _x corrispondente definito dall'utente, viene restituito un errore.In --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015, the compiler interprets this as a user-defined literal, but since there is no matching user-defined literal _x defined, it gives an error.

    error C3688: invalid literal suffix '_x'; literal operator or literal operator template 'operator ""_x' not found  
    note: Did you forget a space between the string literal and the prefix of the following string literal?  
    

    Per risolvere questo problema, aggiungere uno spazio tra il valore letterale stringa e la macro.To fix this problem, add a space between the string literal and the macro.

  • Valori letterali stringa adiacentiAdjacent string literals

    Analogamente al precedente esempio, a causa di modifiche correlate nell'analisi delle stringhe, i valori letterali stringa adiacenti (uno dei valori letterali stringa di carattere wide o narrow) senza gli spazi vuoti sono stati interpretati come una singola stringa concatenata nelle versioni precedenti di Visual C++.Similarly to the previous, due to related changes in string parsing, adjacent string literals (either wide or narrow character string literals) without any whitespace were interpreted as a single concatenated string in previous releases of Visaul C++. In --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015 è necessario aggiungere spazi vuoti tra le due stringhe.In --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015, you must now add whitespace between the two strings. Ad esempio, il codice seguente deve essere modificato:For example, the following code must be changed:

    char * str = "abc""def";  
    

    Aggiungere semplicemente uno spazio tra le due stringhe.Simply add a space in between the two strings.

    char * str = "abc" "def";  
    
  • Operatore new e delete di posizionamentoPlacement new and delete

    È stata apportata una modifica all'operatore delete per fare in modo che sia conforme con lo standard C++14.A change has been made to the delete operator in order to bring it into conformance with C++14 standard. Per informazioni dettagliate sulla modifica agli standard, vedere Deallocazione con dimensione C++.Details of the standards change can be found at C++ Sized Deallocation. Le modifiche aggiungono un modulo dell'operatore delete globale che accetta un parametro di dimensione.The changes add a form of the global delete operator that takes a size parameter. La differenza sostanziale è che se in precedenza si usava un operatore delete con la stessa firma (per la corrispondenza con un operatore new di posizionamento), ora si riceve un errore del compilatore (C2956, che si verifica nel punto in cui viene usato l'operatore new di posizionamento, poiché è la posizione nel codice in cui il compilatore tenta di identificare un operatore delete corrispondente appropriato).The breaking change is that if you were previously using an operator delete with the same signature (to correspond with a placement new operator), you will receive a compiler error (C2956, which occurs at the point where the placement new is used, since that's the position in code where the compiler tries to identify an appropriate matching delete operator).

    La funzione void operator delete(void *, size_t) è un operatore delete di posizionamento corrispondente alla nuova funzione di posizionamento "void * operator new (size_t, size_t)" in C++11.The function void operator delete(void *, size_t) was a placement delete operator corresponding to the placement new function "void * operator new(size_t, size_t)" in C++11. Con la deallocazione con dimensione C++14, questa funzione delete è ora una funzione di deallocazione consueta (operatore delete globale).With C++14 sized deallocation, this delete function is now a usual deallocation function (global delete operator). Lo standard richiede che, se l'uso di un operatore new cerca una funzione delete corrispondente e trova una funzione di deallocazione consueta, il programma non ha un formato corretto.The standard requires that if the use of a placement new looks up a corresponding delete function and finds a usual deallocation function, the program is ill-formed.

    Si supponga, ad esempio, che il codice definisca un operatore new e delete di posizionamento:For example, suppose your code defines both a placement new and a placement delete:

    void * operator new(std::size_t, std::size_t);  
    void operator delete(void*, std::size_t) noexcept;  
    

    Il problema si verifica a causa della corrispondenza delle firme funzione tra un operatore delete di posizionamento che è stato definito e il nuovo operatore delete con dimensione globale.The problem occurs because of the match in function signatures between a placement delete operator you've defined, and the new global sized delete operator. Stabilire se è possibile usare un tipo diverso da size_t per qualsiasi operatore new e delete di posizionamento.Consider whether you can use a different type other than size_t for any placement new and delete operators. Si noti che il tipo di size_t typedef è dipendente dal compilatore; è un typedef per int senza segno in Visual C++.Note that the type of the size_t typedef is compiler-dependent; it is a typedef for unsigned int in Visual C++. Una buona soluzione consiste nell'usare un tipo enumerato simile al seguente:A good solution is to use an enumerated type such as this:

    enum class my_type : size_t {};  
    

    Modificare quindi la definizione dell'operatore new e delete di posizionamento per usare questo tipo come secondo argomento anziché size_t.Then, change your definition of placement new and delete to use this type as the second argument instead of size_t. È necessario anche aggiornare le chiamate all'operatore new di posizionamento per passare al nuovo tipo (ad esempio, usando static_cast<my_type> per convertire il valore integer) e aggiornare la definizione di new e delete per eseguire il cast di tipo integer.You’ll also need to update the calls to placement new to pass the new type (for example, by using static_cast<my_type> to convert from the integer value) and update the definition of new and delete to cast back to the integer type. Non è necessario usare un enum per questo oggetto; funzionerebbe anche un tipo classe con un membro size_t.You don’t need to use an enum for this; a class type with a size_t member would also work.

    Una soluzione alternativa è che si potrebbe eliminare completamente la nuova posizione.An alternative solution is that you might be able to eliminate the placement new altogether. Se il codice usa l'operatore new di posizionamento per implementare un pool di memoria dove l'argomento di posizione è la dimensione dell'oggetto allocato o eliminato, la funzionalità di deallocazione con dimensione potrebbe essere adatta a sostituire il codice del pool di memoria personalizzato ed è possibile eliminare le funzioni di posizionamento e usare semplicemente il proprio operatore delete a due argomenti anziché le funzioni di posizionamento.If your code uses placement new to implement a memory pool where the placement argument is the size of the object being allocated or deleted, then sized deallocation feature might be suitable to replace your own custom memory pool code, and you can get rid of the placement functions and just use your own two-argument delete operator instead of the placement functions.

    Se non si intende aggiornare immediatamente il codice, è possibile ripristinare il comportamento precedente usando l'opzione del compilatore /Zc:sizedDealloc-.If you don't want to update your code immediately, you can revert to the old behavior by using the compiler option /Zc:sizedDealloc-. Se si usa questa opzione, le funzioni di eliminazione a due argomenti non esistono e non provocheranno un conflitto con l'operatore delete di posizionamento.If you use this option, the two-argument delete functions don’t exist and won't cause a conflict with your placement delete operator.

  • Membri dati di unioniUnion data members

    I membri dati di unioni non possono avere tipi di riferimento.Data members of unions can no longer have reference types. Il codice seguente veniva compilato correttamente in --- --- Visual C++ in Visual Studio 2013Visual C++ in Visual Studio 2013, ma produce un errore in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015.The following code compiled successfully in --- --- Visual C++ in Visual Studio 2013Visual C++ in Visual Studio 2013, but produces an error in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015.

    union U1 {  
        const int i;  
    };  
    union U2 {  
       int &i;  
    };  
    union U3 {  
        struct {int &i;};  
    };  
    

    Il codice precedente produce gli errori seguenti:The preceding code produces the following errors:

    test.cpp(67): error C2625: 'U2::i': illegal union member; type 'int &' is reference type  
    test.cpp(70): error C2625: 'U3::i': illegal union member; type 'int &' is reference type  
    

    Per risolvere questo problema, modificare i tipi di riferimento in un puntatore o un valore.To address this issue, change reference types either to a pointer or a value. La modifica del tipo in un puntatore richiede modifiche al codice che usa il campo di unione.Changing the type to a pointer requires changes in the code that uses the union field. La modifica del codice in un valore modificherebbe i dati archiviati nell'unione, che influiscono su altri campi, poiché i campi in tipi di unione condividono la stessa memoria.Changing the code to a value would change the data stored in the union, which affects other fields since fields in union types share the same memory. A seconda delle dimensioni del valore, è possibile anche modificare le dimensioni dell'unione.Depending on the size of the value, it might also change the size of the union.

  • Unioni anonime sono ora più conformi allo standard.Anonymous unions are now more conformant to the standard. Le versioni precedenti del compilatore hanno generato un costruttore e distruttore esplicito per unioni anonime.Previous versions of the compiler generated an explicit constructor and destructor for anonymous unions. Questi vengono eliminati in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015.These are deleted in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015.

    struct S {  
      S();  
     };  
    
     union {  
      struct {  
       S s;  
      };  
     } u; // C2280  
    

    Il codice precedente produce gli errori seguenti in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015:The preceding code generates the following error in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015:

    error C2280: '<unnamed-type-u>::<unnamed-type-u>(void)': attempting to reference a deleted function  
    note: compiler has generated '<unnamed-type-u>::<unnamed-type-u>' here  
    

    Per risolvere questo problema, specificare definizioni personalizzate del costruttore e/o del distruttore.To resolve this issue, provide your own definitions of the constructor and/or destructor.

    struct S {  
    // Provide a default constructor by adding an empty function body.  
    S() {}   
    };  
    
    union {  
    struct {  
    S s;  
    };  
    } u;  
    
  • Unioni con strutture anonimeUnions with anonymous structs

    Per la conformità allo standard, il comportamento di runtime è stato modificato per i membri di strutture anonime nelle unioni.In order to conform with the standard, the runtime behavior has changed for members of anonymous structures in unions. Il costruttore per i membri di strutture anonime in un'unione non viene più chiamato in modo implicito quando viene creato questo tipo di unione.The constructor for anonymous structure members in a union is no longer implicitly called when such a union is created. Il distruttore per i membri di strutture anonime in un'unione non viene più chiamato in modo implicito quando l'unione è esterna all'ambito.Also, the destructor for anonymous structure members in a union is no longer implicitly called when the union goes out of scope. Si consideri il codice seguente, in cui un'unione U contiene una struttura anonima con un membro che è una struttura S denominata con un distruttore.Consider the following code, in which a union U contains an anonymous structure that contains a member which is a named structure S that has a destructor.

    #include <stdio.h>  
    struct S {  
        S() { printf("Creating S\n"); }  
        ~S(){ printf("Destroying S\n"); }  
    };  
    union U {  
        struct {  
        S s;  
    };  
        U() {}  
        ~U(){}  
    };  
    
    void f()  
    {  
        U u;  
        // Destructor implicitly called here.  
    }  
    
    int main()  
    {  
        f();  
    
        char s[1024];  
        printf("Press any key.\n");  
        gets_s(s);  
        return 0;  
    }  
    

    In --- --- Visual C++ in Visual Studio 2013Visual C++ in Visual Studio 2013 il costruttore per S viene chiamato quando viene creata l'unione e il distruttore per S viene chiamato durante la pulitura dello stack per la funzione f.In --- --- Visual C++ in Visual Studio 2013Visual C++ in Visual Studio 2013, the constructor for S is called when the union is created, and the destructor for S is called when the stack for function f is cleaned up. Tuttavia in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015 il costruttore e distruttore non vengono chiamati.But in --- --- Visual C++ in Visual Studio 2015Visual C++ in Visual Studio 2015, the constructor and destructor are not called. Il compilatore visualizza un avviso relativo a questa modifica del comportamento.The compiler gives a warning about this behavior change.

    warning C4587: 'U::s': behavior change: constructor is no longer implicitly calledwarning C4588: 'U::s': behavior change: destructor is no longer implicitly called  
    

    Per ripristinare il comportamento originale, assegnare alla struttura anonima un nome.To restore the original behavior, give the anonymous structure a name. Il comportamento di runtime di strutture non anonime è lo stesso, indipendentemente dalla versione del compilatore.The runtime behavior of non-anonymous structures is the same, regardless of the compiler version.

    #include <stdio.h>  
    
    struct S {  
        S() { printf("Creating S.\n"); }  
        ~S() { printf("Destroying S\n"); }  
    };  
    union U {  
        struct {  
            S s;  
        } namedStruct;  
        U() {}  
        ~U() {}  
    };  
    
    void f()  
    {  
        U u;  
    }  
    
    int main()  
    {  
        f();  
    
        char s[1024];  
        printf("Press any key.\n");  
        gets_s(s);  
        return 0;  
    }  
    

    In alternativa, provare a spostare il codice del costruttore e del distruttore in nuove funzioni e aggiungere chiamate a queste funzioni provenienti dal costruttore e distruttore per l'unione.Alternatively, try moving the constructor and destructor code into new functions, and add calls to these functions from the constructor and destructor for the union.

    #include <stdio.h>  
    
    struct S {  
        void Create() { printf("Creating S.\n"); }  
        void Destroy() { printf("Destroying S\n"); }  
    };  
    union U {  
        struct {  
            S s;  
        };  
        U() { s.Create();  }  
        ~U() { s.Destroy(); }  
    };  
    
    void f()  
    {  
        U u;  
    }  
    
    int main()  
    {  
        f();  
    
    char s[1024];  
    printf("Press any key.\n");  
    gets_s(s);  
    return 0;  
    }  
    
  • Risoluzione per il modelloTemplate resolution

    Sono state apportate modifiche alla risoluzione dei nomi per i modelli.Changes have been made to name resolution for templates. In C++, quando si considerano i candidati per la risoluzione di un nome, può accadere che uno o più nomi presi in considerazione come corrispondenze potenziali producano un'istanza del modello non valida.In C++, when considering candidates for the resolution of a name, it can be the case that one or more names under consideration as potential matches produces an invalid template instantiation. Queste istanze non valide in genere non provocano errori del compilatore, un principio che è noto come SFINAE (Substitution Failure Is Not An Error).These invalid instantiations do not normally cause compiler errors, a principle which is known as SFINAE (Substitution Failure Is Not An Error).

    A questo punto, se SFINAE richiede al compilatore di creare un'istanza di specializzazione del modello di classe, eventuali errori verificatisi durante questo processo sono errori del compilatore.Now, if SFINAE requires the compiler to instantiate the specialization of a class template, then any errors that occur during this process are compiler errors. Nelle versioni precedenti il compilatore potrebbe ignorare tali errori.In previous versions, the compiler would ignore such errors. Si consideri il codice di esempio seguente:For example, consider the following code:

    #include <type_traits>  
    
    template<typename T>  
    struct S  
    {  
    S() = default;  
    S(const S&);  
    S(S&&);  
    
    template<typename U, typename = typename std::enable_if<std::is_base_of<T, U>::value>::type>  
    S(S<U>&&);  
    };  
    
    struct D;  
    
    void f1()  
    {  
    S<D> s1;  
        S<D> s2(s1);  
    }  
    
    struct B  
    {  
    };  
    
    struct D : public B  
    {  
    };  
    
    void f2()  
    {  
    S<D> s1;  
        S<D> s2(s1);  
    }  
    

    Se si compila con il compilatore corrente, viene visualizzato l'errore seguente:If you compile with the current compiler, you get the following error:

    type_traits(1110): error C2139: 'D': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_base_of'  
    ..\t331.cpp(14): note: see declaration of 'D'  
    ..\t331.cpp(10): note: see reference to class template instantiation 'std::is_base_of<T,U>' being compiled  
            with  
            [  
                T=D,  
                U=D  
            ]  
    

    Ciò accade perché al momento della prima chiamata di is_base_of la classe 'D' non è stata definita.This is because at the point of the first invocation of the is_base_of the class 'D' has not yet been defined.

    In questo caso, la correzione non deve usare tale tratti di tipo fino a quando non è stata definita la classe.In this case, the fix is not to use such type traits until the class has been defined. Se si spostano le definizioni di B e D all'inizio del file di codice, l'errore viene risolto.If you move the definitions of B and D to the beginning of the code file, the error is resolved. Se le definizioni sono nei file di intestazione, controllare l'ordine delle istruzioni include per i file di intestazione per verificare che tutte le definizioni di classe vengano compilate prima di usare modelli problematici.If the definitions are in header files, check the order of the include statements for the header files to make sure that any class definitions are compiled before the problematic templates are used.

  • Costruttori di copiaCopy constructors

    Sia in --- --- Visual Studio 2013Visual Studio 2013 che in Visual Studio 2015 il compilatore genera un costruttore di copia per una classe se tale classe ha un costruttore di spostamento definito dall'utente, ma nessun costruttore di copia definito dall'utente.In both --- --- Visual Studio 2013Visual Studio 2013 and Visual Studio 2015, the compiler generates a copy constructor for a class if that class has a user-defined move constructor but no user-defined copy constructor. In Dev14, questo costruttore di copia generato in modo implicito è contrassegnato come "= delete".In Dev14, this implicitly generated copy constructor is also marked "= delete".

Miglioramenti della conformità in Update 1 Conformance Improvements in Update 1

  • Classi base virtuali private ed ereditarietà indirettaPrivate virtual base classes and indirect inheritance

    Le versioni precedenti del compilatore consentivano a una classe derivata di chiamare le funzioni di membro relative alle classi base indirettamente derivateprivate virtual.Previous versions of the compiler allowed a derived class to call member functions of its indirectly-derivedprivate virtual base classes. Questo comportamento precedente non era corretto e non è conforme allo standard C++.This old behavior was incorrect and does not conform to the C++ standard. Il compilatore non accetta più il codice scritto in questo modo e genera l'errore del compilatore C2280 di conseguenza.The compiler no longer accepts code written in this way and issues compiler error C2280 as a result.

    error C2280: 'void *S3::__delDtor(unsigned int)': attempting to reference a deleted function  
    

    Esempio (prima)Example (before)

    class base  
    {  
    protected:  
        base();  
        ~base();  
    };  
    
    class middle: private virtual base {};class top: public virtual middle {};  
    
    void destroy(top *p)  
    {  
        delete p;  //   
    }  
    

    Esempio (dopo)Example (after)

    class base;  // as above  
    
    class middle: protected virtual base {};  
    class top: public virtual middle {};  
    
    void destroy(top *p)  
    {  
        delete p;  
    }  
    

    -oppure--or-

    class base;  // as above  
    
    class middle: private virtual base {};  
    class top: public virtual middle, private virtual bottom {};  
    
    void destroy(top *p)  
    {  
        delete p;  
    }  
    
  • Funzioni operator new e operator delete in overloadOverloaded operator new and operator delete

    Le versioni precedenti del compilatore consentivano di dichiarare static le funzioni non membro operator new e non membro operator delete negli spazi dei nomi diversi dallo spazio dei nomi globale.Previous versions of the compiler allowed non-member operator new and non-member operator delete to be declared static, and to be declared in namespaces other than the global namespace. Questo comportamento precedente creava il rischio che il programma non chiamasse l'implementazione dell'operator new o delete prevista dal programmatore, determinando un comportamento errato in fase di esecuzione senza avvisare.This old behavior created a risk that the program would not call the new or delete operator implementation that the programmer intended, resulting in silent bad runtime behavior. Il compilatore non accetta più il codice scritto in questo modo e genera invece l'errore del compilatore C2323.The compiler no longer accepts code written in this way and issues compiler error C2323 instead.

    error C2323: 'operator new': non-member operator new or delete functions may not be declared static or in a namespace other than the global namespace.  
    

    Esempio (prima)Example (before)

    static inline void * __cdecl operator new(size_t cb, const std::nothrow_t&)  // error C2323  
    

    Esempio (dopo)Example (after)

    void * __cdecl operator new(size_t cb, const std::nothrow_t&)  // removed 'static inline'  
    

    Inoltre, nonostante il compilatore non fornisca una diagnostica specifica, il formato dell'operatore new inline viene considerato non valido.Additionally, although the compiler doesn't give a specific diagnostic, inline operator new is considered ill-formed.

  • Chiamata di 'operator type()' (conversione definita dall'utente) in tipi non classeCalling 'operator type()' (user-defined conversion) on non-class types

    Le versioni precedenti del compilatore consentivano di chiamare 'operator type()' su tipi non classe ignorandolo senza avvisare.Previous versions of the compiler allowed 'operator type()' to be called on non-class types while silently ignoring it. Questo comportamento precedente creava un rischio di generazione di codice errato senza avvisare, determinando un comportamento imprevedibile in fase di esecuzione.This old behavior created a risk of silent bad code generation, resulting in unpredictable runtime behavior. Il compilatore non accetta più il codice scritto in questo modo e genera invece l'errore del compilatore C2228.The compiler no longer accepts code written in this way and issues compiler error C2228 instead.

    error C2228: left of '.operator type' must have class/struct/union  
    

    Esempio (prima)Example (before)

    typedef int index_t;  
    
    void bounds_check(index_t index);  
    
    void login(int column)  
    {  
        bounds_check(column.operator index_t());  // error C2228  
    }  
    

    Esempio (dopo)Example (after)

    typedef int index_t;  
    
    void bounds_check(index_t index);  
    
    void login(int column)  
    {  
        bounds_check(column);  // removed cast to 'index_t', 'index_t' is an alias of 'int'  
    }  
    
  • Typename ridondante negli identificatori di tipi elaboratiRedundant typename in elaborated type specifiers

    Le versioni precedenti del compilatore consentivano typename negli identificatori di tipi elaborati; il codice scritto in questo modo non è semanticamente corretto.Previous versions of the compiler allowed typename in an elaborated type specifiers; code written in this way is semantically incorrect. Il compilatore non accetta più il codice scritto in questo modo e genera invece l'errore del compilatore C3406.The compiler no longer accepts code written in this way and issues compiler error C3406 instead.

    error C3406: 'typename' cannot be used in an elaborated type specifier  
    

    Esempio (prima)Example (before)

    template <typename class T>  
    class container;  
    

    Esempio (dopo)Example (after)

    template <class T>  // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case  
    class container;  
    
  • Deduzione del tipo di matrici da un elenco di inizializzatoriType deduction of arrays from an initializer list

    Le versioni precedenti del compilatore non supportavano la deduzione del tipo di matrici da un elenco di inizializzatori.Previous versions of the compiler did not support type deduction of arrays from an initializer list. Il compilatore supporta ora questa forma di deduzione del tipo e, di conseguenza, le chiamate a modelli di funzione con gli elenchi di inizializzatori potrebbero essere ambigue o potrebbe essere scelto un altro overload rispetto alle versioni precedenti del compilatore.The compiler now supports this form of type deduction and, as a result, calls to function templates using initializer lists might now be ambiguous or a different overload might be chosen than in previous versions of the compiler. Per risolvere questi problemi, il programma deve ora specificare in modo esplicito l'overload previsto dal programmatore.To resolve these issues, the program must now explicitly specify the overload that the programmer intended.

    Quando questo nuovo comportamento fa sì che la risoluzione dell'overload consideri un candidato aggiuntivo che sia altrettanto efficace del candidato storico, la chiamata diventa ambigua e il compilatore genera l'errore del compilatore C2668 di conseguenza.When this new behavior causes overload resolution to consider an additional candidate that is equally as good as the historic candidate, the call becomes ambiguous and the compiler issues compiler error C2668 as a result.

    error C2668: 'function' : ambiguous call to overloaded function.  
    

    Esempio 1: chiamata ambigua a funzione in overload (prima)Example 1: Ambiguous call to overloaded function (before)

    // In previous versions of the compiler, code written in this way would unambiguously call f(int, Args...)  
    template <typename... Args>  
    void f(int, Args...);  //   
    
    template <int N, typename... Args>  
    void f(const int (&)[N], Args...);  
    
    int main()  
    {  
        // The compiler now considers this call ambiguous, and issues a compiler error  
        f({3});  error C2668: 'f' ambiguous call to overloaded function  
    }  
    

    Esempio 1: chiamata ambigua a funzione in overload (dopo)Example 1: ambiguous call to overloaded function (after)

    template <typename... Args>  
    void f(int, Args...);  //   
    
    template <int N, typename... Args>  
    void f(const int (&)[N], Args...);  
    
    int main()  
    {  
        // To call f(int, Args...) when there is just one expression in the initializer list, remove the braces from it.  
        f(3);  
    }  
    

    Quando questo nuovo comportamento fa sì che la risoluzione dell'overload consideri un candidato aggiuntivo che sia una corrispondenza migliore rispetto al candidato storico, la chiamata viene risolta senza ambiguità nel nuovo candidato, causando una modifica nel comportamento del programma che è probabilmente diverso da quello previsto dal programmatore.When this new behavior causes overload resolution to consider an additional candidate that is a better match than the historic candidate, the call resolves unambiguously to the new candidate, causing a change in program behavior that is probably different than the programmer intended.

    Esempio 2: modifica nella risoluzione dell'overload (prima)Example 2: change in overload resolution (before)

    // In previous versions of the compiler, code written in this way would unambiguously call f(S, Args...)  
    struct S  
    {  
        int i;  
        int j;  
    };  
    
    template <typename... Args>  
    void f(S, Args...);  
    
    template <int N, typename... Args>  
    void f(const int *&)[N], Args...);  
    
    int main()  
    {  
        // The compiler now resolves this call to f(const int (&)[N], Args...) instead  
        f({1, 2});  
    }  
    

    Esempio 2: modifica nella risoluzione dell'overload (dopo)Example 2: change in overload resolution (after)

    struct S;  // as before  
    
    template <typename... Args>  
    void f(S, Args...);  
    
    template <int N, typename... Args>  
    void f(const int *&)[N], Args...);  
    
    int main()  
    {  
        // To call f(S, Args...), perform an explicit cast to S on the initializer list.  
        f(S{1, 2});  
    }  
    
  • Ripristino di avvisi di istruzione switchRestoration of switch statement warnings

    Una versione precedente del compilatore rimuoveva gli avvisi preesistenti correlati alle istruzioni switch ; questi avvisi sono ora stati ripristinati.A Previous version of the compiler removed previously-existing warnings related to switch statements; these warnings have now been restored. Il compilatore genera ora gli avvisi ripristinati e gli avvisi correlati a casi specifici (incluso il caso predefinito) sono ora rilasciati sulla riga contenente il caso che causa l'errore, anziché l'ultima riga dell'istruzione switch.The compiler now issues the restored warnings, and warnings related to specific cases (including the default case) are now issued on the line containing the offending case, rather than on the last line of the switch statement. Dal momento che gli avvisi vengono ora emessi su diverse righe rispetto al passato, di conseguenza gli avvisi precedentemente eliminato con #pragma warning(disable:####) non potranno più essere eliminati come previsto.As a result of now issuing those warnings on different lines than in the past, warnings previously suppressed by using #pragma warning(disable:####) may no longer be suppressed as intended. Per eliminare questi avvisi come previsto, potrebbe essere necessario spostare la direttiva #pragma warning(disable:####) a una riga sopra il primo caso potenzialmente danneggiato.To suppress these warnings as intended, it might be necessary to move the #pragma warning(disable:####) directive to a line above the first potentially-offending case. Di seguito sono elencati gli avvisi ripristinati.The following are the restored warnings.

    warning C4060: switch statement contains no 'case' or 'default' labels  
    
    warning C4061: enumerator 'bit1' in switch of enum 'flags' is not explicitly handled by a case label  
    
    warning C4062: enumerator 'bit1' in switch of enum 'flags' is not handled  
    
    warning C4063: case 'bit32' is not a valid value for switch of enum 'flags'  
    
    warning C4064: switch of incomplete enum 'flags'  
    
    warning C4065: switch statement contains 'default' but no 'case' labels  
    
    warning C4808: case 'value' is not a valid value for switch condition of type 'bool'  
    
    Warning C4809: switch statement has redundant 'default' label; all possible 'case' labels are given  
    

    Esempio di C4063 (prima)Example of C4063 (before)

    class settings  
    {  
    public:  
        enum flags  
        {  
            bit0 = 0x1,  
            bit1 = 0x2,  
            ...  
        };  
        ...  
    };  
    
    int main()  
    {  
        auto val = settings::bit1;  
    
        switch (val)  
        {  
        case settings::bit0:  
            break;  
    
        case settings::bit1:  
            break;  
    
        case settings::bit0 | settings::bit1:  // warning C4063  
            break;  
        }  
    };  
    

    Esempio di C4063 (dopo)Example of C4063 (after)

    class settings {...};  // as above  
    
    int main()  
    {  
        // since C++11, use std::underlying_type to determine the underlying type of an enum  
        typedef std::underlying_type<settings::flags>::type flags_t;  
    
        auto val = settings::bit1;  
    
        switch (static_cast<flags_t>(val))  
        {  
        case settings::bit0:  
            break;  
    
        case settings::bit1:  
            break;  
    
        case settings::bit0 | settings::bit1:  // ok  
            break;  
        }  
    };  
    

    Gli esempi di altri avvisi ripristinati vengono forniti nella relativa documentazione.Examples of the other restored warnings are provided in their documentation.

  • #include: usare l'identificatore di directory padre '..' nel percorso (influisce solo su /Wall /WX)#include: use of parent-directory specifier '..' in pathname (only affects /Wall /WX)

    Le versioni precedenti del compilatore non è stato rilevato l’utilizzo dell’identificatore di directory padre ‘... ‘Previous versions of the compiler did not detect the use of the parent-directory specifier '..' nel percorso del #include direttive.in the pathname of #include directives. Il codice scritto in questo modo è in genere usato in modo da includere le intestazioni che esistono di fuori del progetto usando in modo non corretto percorsi relativi al progetto.Code written in this way is usually intended to include headers that exist outside of the project by incorrectly using project-relative paths. Questo comportamento precedente creava il rischio che il programma potesse essere compilato con l'inclusione di un file di origine diversa rispetto a quello previsto dal programmatore, o che i percorsi relativi non sarebbero stati portabili in altri ambienti di compilazione.This old behavior created a risk that the program could be compiled by including a different source file than the programmer intended, or that these relative paths would not be portable to other build environments. Il compilatore ora rileva e invia una notifica al programmatore riguardo il codice scritto in questo modo e genera un avviso del compilatore C4464 facoltativo, se abilitato.The compiler now detects and notifies the programmer of code written in this way and issues an optional compiler warning C4464, if enabled.

    warning C4464: relative include path contains '..'  
    

    Esempio (prima)Example (before)

    #include "..\headers\C4426.h"  // emits warning C4464  
    

    Esempio (dopo)Example (after)

    #include "C4426.h"  // add absolute path to 'headers\' to your project's include directories  
    

    Inoltre, nonostante il compilatore non offra una diagnostica specifica, è anche consigliabile che l'identificatore di directory padre ".." non venga usato per specificare le directory include del progetto.Additionally, although the compiler does not give a specific diagnostic, we also recommend that the parent-directory specifier ".." should note be used to specify your project's include directories.

  • #pragma optimize() estende oltre la fine del file di intestazione (influisce solo su /Wall /WX)#pragma optimize() extends past end of header file (only affects /Wall /WX)

    Le versioni precedenti del compilatore non rilevavano le modifiche alle impostazioni del flag di ottimizzazione non incluse in un file di intestazione all'interno di un'unità di conversione.Previous versions of the compiler did not detect changes to optimization flag settings that escape a header file included within a translation unit. Il compilatore ora rileva e invia una notifica al programmatore riguardo il codice scritto in questo modo e genera un avviso del compilatore C4426 facoltativo nella posizione della direttiva #includedanneggiata, se abilitata.The compiler now detects and notifies the programmer of code written in this way and issues an optional compiler warning C4426 at the location of the offending #include, if enabled. Questo avviso viene generato solo se le modifiche sono in conflitto con i flag di ottimizzazione impostati dagli argomenti della riga di comando nel compilatore.This warning is only issued if the changes conflict with the optimization flags set by command-line arguments to the compiler.

    warning C4426: optimization flags changed after including header, may be due to #pragma optimize()  
    

    Esempio (prima)Example (before)

    // C4426.h  
    #pragma optimize("g", off)  
    ...  
    // C4426.h ends  
    
    // C4426.cpp  
    #include "C4426.h"  // warning C4426  
    

    Esempio (dopo)Example (after)

    // C4426.h  
    #pragma optimize("g", off)  
    ...  
    #pragma optimize("", on)  // restores optimization flags set via command-line arguments  
    // C4426.h ends  
    
    // C4426.cpp  
    #include "C4426.h"  
    
  • Stati #pragma warning(push) e #pragma warning(pop) (influisce solo su /Wall /WX)Mismatched #pragma warning(push) and #pragma warning(pop) (only affects /Wall /WX)

    Le versioni precedenti del compilatore non rilevavano l'abbinamento delle modifiche di stato #pragma warning(push) con le modifiche di stato #pragma warning(pop) in un file di origine differente e questo raramente rappresenta lo scopo previsto.Previous versions of the compiler did not detect #pragma warning(push) state changes being paired with #pragma warning(pop) state changes in a different source file, which is rarely intended. Questo comportamento precedente creava il rischio che il programma fosse compilato con un set di avvisi abilitato diverso da quello previsto dal programmatore, determinando un probabile comportamento errato in fase di esecuzione senza avvisare.This old behavior created a risk that the program would be compiled with a different set of warnings enabled than the programmer intended, possibly resulting in silent bad runtime behavior. Il compilatore ora rileva e invia una notifica al programmatore riguardo al codice scritto in questo modo e genera un avviso del compilatore C5031 facoltativo nella posizione della direttiva #pragma warning(pop) corrispondente, se abilitata.The compiler now detects and notifies the programmer of code written in this way and issues an optional compiler warning C5031 at the location of the matching #pragma warning(pop), if enabled. Questo avviso include una nota che fa riferimento alla posizione della direttiva #pragma warning(push) corrispondente.This warning includes a note referencing the location of the corresponding #pragma warning(push).

    warning C5031: #pragma warning(pop): likely mismatch, popping warning state pushed in different file  
    

    Esempio (prima)Example (before)

    // C5031_part1.h  
    #pragma warning(push)  
    #pragma warning(disable:####)  
    ...  
    // C5031_part1.h ends without #pragma warning(pop)  
    
    // C5031_part2.h  
    ...  
    #pragma warning(pop)  // pops a warning state not pushed in this source file   
    ...  
    // C5031_part1.h ends  
    
    // C5031.cpp  
    #include "C5031_part1.h" // leaves #pragma warning(push) 'dangling'  
    ...  
    #include "C5031_part2.h" // matches 'dangling' #pragma warning(push), resulting in warning C5031  
    ...  
    

    Esempio (dopo)Example (after)

    // C5031_part1.h  
    #pragma warning(push)  
    #pragma warning(disable:####)  
    ...  
    #pragma warning(pop)  // pops the warning state pushed in this source file  
    // C5031_part1.h ends without #pragma warning(pop)  
    
    // C5031_part2.h  
    #pragma warning(push)  // pushes the warning state pushed in this source file  
    #pragma warning(disable:####)  
    ...  
    #pragma warning(pop)  
    // C5031_part1.h ends  
    
    // C5031.cpp  
    #include "C5031_part1.h" // #pragma warning state changes are self-contained and independent of other source files or their #include order.  
    ...  
    #include "C5031_part2.h"  
    ...  
    

    Benché sia un fatto insolito, a volte il codice scritto in questo modo è intenzionale.Though uncommon, code written in this way is sometimes intentional. Il codice scritto in questo modo è sensibile alle modifiche nell'ordine #include. Se possibile, è consigliabile che i file del codice sorgente gestiscano lo stato di avviso in modo autonomo.Code written in this way is sensitive to changes in #include order; when possible, we recommend that source code files manage warning state in a self-contained way.

  • Stato #pragma warning(push) senza corrispondenza (influisce solo su /Wall /WX)Unmatched #pragma warning(push) (only affects /Wall /WX)

    Le versioni precedenti del compilatore non rilevavano modifiche di stato #pragma warning(push) senza corrispondenza alla fine di un'unità di conversione.Previous versions of the compiler did not detect unmatched #pragma warning(push) state changes at the end of a translation unit. Il compilatore ora rileva e invia una notifica al programmatore riguardo il codice scritto in questo modo e genera un avviso del compilatore C5032 nella posizione della direttiva #pragma warning(push) senza corrispondenza, se abilitata.The compiler now detects and notifies the programmer of code written in this way and issues an optional compiler warning C5032 at the location of the unmatched #pragma warning(push), if enabled. Questo avviso viene generato solo se non sono presenti errori di compilazione nell'unità di conversione.This warning is only issued if there are no compilation errors in the translation unit.

    warning C5032: detected #pragma warning(push) with no corresponding #pragma warning(pop)  
    

    Esempio (prima)Example (before)

    // C5032.h  
    #pragma warning(push)  
    #pragma warning(disable:####)  
    ...  
    // C5032.h ends without #pragma warning(pop)  
    
    // C5032.cpp  
    #include "C5032.h"  
    ...  
    // C5032.cpp ends -- the translation unit is completed without #pragma warning(pop), resulting in warning C5032 on line 1 of C5032.h  
    

    Esempio (dopo)Example (after)

    // C5032.h  
    #pragma warning(push)  
    #pragma warning(disable:####)  
    ...  
    #pragma warning(pop) // matches #pragma warning (push) on line 1  
    // C5032.h ends  
    
    // C5032.cpp  
    #include "C5032.h"  
    ...  
    // C5032.cpp ends -- the translation unit is completed without unmatched #pragma warning(push)  
    
  • Potrebbero essere generati avvisi aggiuntivi in seguito al migliorato rilevamento dello stato della direttiva #pragma warningAdditional warnings might be issued as a result of improved #pragma warning state tracking

    Le versioni precedenti del compilatore rilevavano le modifiche di stato della direttiva #pragma warning in maniera non sufficiente a generare tutti gli avvisi previsti.Previous versions of the compiler tracked #pragma warning state changes insufficiently well to issue all intended warnings. Questo comportamento comportava il rischio che alcuni avvisi sarebbero stati eliminati in modo efficace in circostanze diverse rispetto a quelle previste dal programmatore.This behavior created a risk that certain warnings would be effectively suppressed in circumstances different than the programmer intended. Il compilatore ora tiene traccia dello stato della direttiva #pragma warning in modo più affidabile, specialmente per quanto riguarda le modifiche dello stato della direttiva #pragma warning all'interno dei modelli, e facoltativamente rilascia nuovi avvisi C5031 e C5032 che aiutano il programmatore a trovare gli usi imprevisti di #pragma warning(push) e #pragma warning(pop).The compiler now tracks #pragma warning state more robustly -- especially related to #pragma warning state changes inside of templates -- and optionally issues new warnings C5031 and C5032 which are intended to help the programmer locate unintended uses of #pragma warning(push) and #pragma warning(pop).

    In seguito al migliorato rilevamento delle modifiche di stato della direttiva #pragma warning, è ora possibile generare gli avvisi in precedenza eliminati in modo errato oppure gli avvisi relativi ai problemi in precedenza diagnosticati in modo errato.As a result of improved #pragma warning state change tracking, warnings formerly incorrectly suppressed or warnings related to issues formerly misdiagnosed might now be issued.

  • Identificazione del codice non eseguibile migliorataImproved identification of unreachable code

    Le modifiche della Libreria standard C++ e la migliorata capacità di incorporare le chiamate di funzione inline rispetto alle versioni precedenti del compilatore potrebbero consentire al compilatore di dimostrare che determinato codice è ora non eseguibile.C++ Standard Library changes and improved ability to inline function calls over previous versions of the compiler might allow the compiler to prove that certain code is now unreachable. Questo nuovo comportamento può comportare nuove e più frequenti visualizzazioni dell'avviso C4720.This new behavior can result in new and more-frequently issued instances of warning C4720.

    warning C4720: unreachable code  
    

    In molti casi, l'avviso potrebbe essere generato solo durante la compilazione con ottimizzazioni abilitate, dal momento che le ottimizzazioni potrebbero incorporare più chiamate di funzione, eliminare il codice ridondante o altrimenti consentire di determinare che determinato codice non è eseguibile.In many cases, this warning might only be issued when compiling with optimizations enabled, since optimizations may inline more function calls, eliminate redundant code, or otherwise make it possible to determine that certain code is unreachable. Si è osservato che le nuove istanze dell'avviso C4720 si sono verificate di frequente nei blocchi try/catch, in special modo in relazione all'uso di std::find.We have observed that new instances of warning C4720 have frequently occurred in try/catch blocks, especially in relation to use of std::find.

    Esempio (prima)Example (before)

    try   
    {   
        auto iter = std::find(v.begin(), v.end(), 5);   
    }   
    catch(...)   
    {   
        do_something();  // ok   
    }  
    

    Esempio (dopo)Example (after)

    try   
    {   
        auto iter = std::find(v.begin(), v.end(), 5);   
    }   
    catch(...)   
    {   
        do_something();  // warning C4702: unreachable code  
    }  
    

Miglioramenti della conformità in Update 2 Conformance Improvements in Update 2

  • Errori e avvisi aggiuntivi potrebbero essere generati in seguito a un supporto parziale per l'espressione SFINAEAdditional warnings and errors might be issued as a result of partial support for expression SFINAE

    Le versioni precedenti del compilatore non analizzavano alcuni tipi di espressioni negli identificatori decltype a causa della mancanza di supporto per l'espressione SFINAE.Previous versions of the compiler did not parse certain kinds of expressions inside decltype specifiers due to lack of support for expression SFINAE. Questo comportamento precedente non era corretto e non è conforme allo standard C++.This old behavior was incorrect and does not conform to the C++ standard. Grazie ai costanti miglioramenti alla conformità, ora il compilatore analizza le espressioni e ha un supporto parziale per l'espressione SFINAE.The compiler now parses these expressions and has partial support for expression SFINAE due to ongoing conformance improvements. Di conseguenza, ora vengono visualizzati avvisi ed errori rilevati nelle espressioni non analizzati dalle versioni precedenti del compilatore.As a result, the compiler now issues warnings and errors found in expressions that previous versions of the compiler did not parse.

    Quando questo nuovo comportamento analizza un'espressione decltype che include un tipo non ancora dichiarato, il compilatore genera l'errore C2039.When this new behavior parses a decltype expression that includes a type that has not yet been declared, the compiler issues compiler error C2039 as a result.

    error C2039: 'type': is not a member of '`global namespace''  
    

    Esempio 1: uso di un tipo non dichiarato (prima)Example 1: use of an undeclared type (before)

    struct s1  
    {  
      template <typename T>  
      auto f() -> decltype(s2<T>::type::f());  // error C2039  
    
      template<typename>  
      struct s2 {};  
    }  
    

    Esempio 1 (dopo)Example 1 (after)

    struct s1  
    {  
      template <typename>  // forward declare s2struct s2;  
    
      template <typename T>  
      auto f() -> decltype(s2<T>::type::f());  
    
      template<typename>  
      struct s2 {};  
    }  
    

    Quando questo nuovo comportamento analizza un'espressione decltype in cui non è presente un utilizzo necessario della parola chiave typename per specificare che il nome dipendente è un tipo, il compilatore genera l'avviso C4346 e l'errore C2923.When this new behavior parses a decltype expression that is missing a necessary use of the typename keyword to specify that a dependent name is a type, the compiler issues compiler warning C4346 together with compiler error C2923.

    warning C4346: 'S2<T>::Type': dependent name is not a type  
    
    error C2923: 's1': 'S2<T>::Type' is not a valid template type argument for parameter 'T'  
    

    Esempio 2: il nome dipendente non è un tipo (prima)Example 2: dependent name is not a type (before)

    template <typename T>  
    struct s1  
    {  
      typedef T type;  
    };  
    
    template <typename T>  
    struct s2  
    {  
      typedef T type;  
    };  
    
    template <typename T>  
    T declval();  
    
    struct s  
    {  
      template <typename T>  
      auto f(T t) -> decltype(t(declval<S1<S2<T>::type>::type>()));  // warning C4346, error C2923  
    };  
    

    Esempio 2 (dopo)Example 2 (after)

    template <typename T> struct s1 {...};  // as above  
    template <typename T> struct s2 {...};  // as above  
    
    template <typename T>  
    T declval();  
    
    struct s  
    {  
      template <typename T>  
      auto f(T t) -> decltype(t(declval<S1<typename S2<T>::type>::type>()));  
    };  
    
  • volatile Le variabili membro impediscono i costruttori e gli operatori di assegnazione definiti in modo implicitovolatile member variables prevent implicitly defined constructors and assignment operators

    Le versioni precedenti del compilatore consentivano a una classe con variabili membro volatile di generare automaticamente costruttori di copia/spostamento predefiniti e operatori di assegnazione di copia/spostamento predefiniti.Previous versions of the compiler allowed a class that has volatile member variables to have default copy/move constructors and default copy/move assignment operators automatically generated. Questo comportamento precedente non era corretto e non è conforme allo standard C++.This old behavior was incorrect and does not conform to the C++ standard. Ora il compilatore presuppone che una classe con variabili membro volatili includa operatori di costruzione e di assegnazione non semplici e, di conseguenza, impedisce la generazione automatica delle implementazioni predefinite di questi operatori.The compiler now considers a class that has volatile member variables to have non-trivial construction and assignment operators which prevents default implementations of these operators from being automatically generated. Quando questa classe è un membro di un'unione (o un'unione anonima all'interno di una classe), i costruttori di copia/spostamento e gli operatori di assegnazione di copia/spostamento dell'unione (o della classe che contiene l'unione anonima) vengono definiti in modo implicito come eliminati.When such a class is a member of a union (or an anonymous union inside of a class), the copy/move constructors and copy/move assignment operators of the union (or the class containing the unonymous union) will be implicitly defined as deleted. Il tentativo di costruire o copiare l'unione (o la classe che contiene l'unione anonima) senza definirli in modo esplicito è un errore e, di conseguenza, il compilatore genera l'errore C2280.Attempting to construct or copy the union (or class containing the anonymous union) without explicitly defining them is an error and the compiler issues compiler error C2280 as a result.

    error C2280: 'B::B(const B &)': attempting to reference a deleted function  
    

    Esempio (prima)Example (before)

    struct A  
    {  
      volatile int i;  
      volatile int j;  
    };  
    
    extern A* pa;  
    
    struct B  
    {  
      union  
      {  
        A a;  
        int i;  
      };  
    };  
    
    B b1 {*pa};  
    B b2 (b1);  // error C2280  
    

    Esempio (dopo)Example (after)

    struct A  
    {  
      int i;int j;  
    };  
    
    extern volatile A* pa;  
    
    A getA()  // returns an A instance copied from contents of pa  
    {  
      A a;  
      a.i = pa->i;  
      a.j = pa->j;  
      return a;  
    }  
    
    struct B;  // as above  
    
    B b1 {GetA()};  
    B b2 (b1);  // error C2280  
    
  • Le funzioni membro statiche non supportano i qualificatori CV.Static member functions do not support cv-qualifiers.

    Le versioni precedenti di Visual C++ 2015 consentivano alle funzioni membro statiche di avere qualificatori CV.Previous versions of Visual C++ 2015 allowed static member functions to have cv-qualifiers. Questo comportamento è dovuto a una regressione in Visual C++ 2015 e Visual C++ 2015 Update 1. Visual C++ 2013 e le versioni precedenti di Visual C++ non accettano il codice scritto in questo modo.This behavior is due to a regression in Visual C++ 2015 and Visual C++ 2015 Update 1; Visual C++ 2013 and previous versions of Visual C++ reject code written in this way. Il comportamento di Visual C++ 2015 e Visual C++ 2015 Update 1 non è corretto e non è conforme allo standard C++.The behavior of Visual C++ 2015 and Visual C++ 2015 Update 1 is incorrect and does not conform to the C++ standard. Visual Studio 2015 Update 2 non accetta il codice scritto in questo modo e genera l'errore del compilatore C2511.Visual Studio 2015 Update 2 rejects code written in this way and issues compiler error C2511 instead.

    error C2511: 'void A::func(void) const': overloaded member function not found in 'A'  
    

    Esempio (prima)Example (before)

    struct A  
    {  
      static void func();  
    };  
    
    void A::func() const {}  // C2511  
    

    Esempio (dopo)Example (after)

    struct A  
    {  
      static void func();  
    };  
    
    void A::func() {}  // removed const  
    
  • La dichiarazione con prototipo di tipo enum non è consentita nel codice WinRT (interessa solo /ZW)Forward declaration of enum is not allowed in WinRT code (affects /ZW only)

    Il codice compilato per Windows Runtime (WinRT) non consente la dichiarazione con prototipo dei tipi enum, analogamente a quanto accade quando il codice C++ gestito viene compilato per .NET Framework usando l'opzione /clr del compilatore.Code compiled for the Windows Runtime (WinRT) doesn't allow enum types to be forward declared, similarly to when managed C++ code is compiled for the .Net Framework using the /clr compiler switch. Questo comportamento garantisce che le dimensioni di un'enumerazione siano sempre note e possano essere proiettate correttamente nel sistema di tipi WinRT.This behavior is ensures that the size of an enumeration is always known and can be correctly projected to the WinRT type system. Il compilatore non accetta il codice scritto in questo modo e genera gli errori C2599 e C3197.The compiler rejects code written in this way and issues compiler error C2599 together with compiler error C3197.

    error C2599: 'CustomEnum': the forward declaration of a WinRT enum is not allowed  
    
    error C3197: 'public': can only be used in definitions  
    

    Esempio (prima)Example (before)

    namespace A {  
      public enum class CustomEnum: int32;  // forward declaration; error C2599, error C3197  
    }  
    
    namespace A {  
      public enum class CustomEnum: int32  
      {  
        Value1  
      };  
    }  
    
    public ref class Component sealed  
    {  
    public:  
      CustomEnum f()  
      {  
        return CustomEnum::Value1;  
      }  
    };  
    

    Esempio (dopo)Example (after)

              // forward declaration of CustomEnum removed  
    
    namespace A {  
      public enum class CustomEnum: int32  
      {  
        Value1  
      };  
    }  
    
    public ref class Component sealed  
    {  
    public:  
      CustomEnum f()  
      {  
        return CustomEnum::Value1;  
      }  
    };  
    
  • È possibile che le funzioni new o delete dell'operatore non membro in overload non siano dichiarate come inline (livello 1 (/W1) attivato per impostazione predefinita)Overloaded non-member operator new and operator delete may not be declared inline (Level 1 (/W1) on-by-default)

    Le versioni precedenti del compilatore non generano un avviso quando le funzioni new e delete di un operatore non membro vengono dichiarate inline.Previous versions of the compiler do not issue a warning when non-member operator new and operator delete functions are declared inline. Il codice scritto in questo modo non è valido (diagnostica non necessaria) e può causare problemi di memoria difficili da diagnosticare derivanti dalla mancata corrispondenza degli operatori new e delete (in particolare quando sono usati insieme con la deallocazione dimensionata).Code written in this way is ill-formed (no diagnostic required) and can cause memory issues resulting from mismatched new and delete operators (especially when used together with sized deallocation) that can be difficult to diagnose. Ora il compilatore genera l'avviso C4595 per identificare il codice scritto in questo modo.The compiler now issues compiler warning C4595 to help identify code written in this way.

    warning C4595: 'operator new': non-member operator new or delete functions may not be declared inline  
    

    Esempio (prima)Example (before)

              inline void* operator new(size_t sz)  // warning C4595  
    {  
      ...  
    }  
    

    Esempio (dopo)Example (after)

              void* operator new(size_t sz)  // removed inline  
    {  
      ...  
    }  
    

    La correzione del codice scritto in questo modo potrebbe richiedere lo spostamento delle definizioni dell'operatore da un file di intestazione a un file di origine corrispondente.Fixing code that's written in this way might require that the operator definitions be moved out of a header file and into a corresponding source file.

Miglioramenti della conformità in Update 3 Conformance Improvements in Update 3

  • std::is_convertable ora rileva l'assegnazione automatica (libreria standard)std::is_convertable now detects self-assignment (standard library)

    Le versioni precedenti del tratto di tipo std::is_convertable non rilevano correttamente l'assegnazione automatica di un tipo di classe quando il relativo costruttore di copia è eliminato o privato.Previous versions of the std::is_convertable type-trait did not correctly detect self-assignment of a class type when its copy constructor is deleted or private. Ora std::is_convertable<>::value è impostato correttamente su false quando è applicato a un tipo di classe con costruttore di copia privato o eliminato.Now, std::is_convertable<>::value is correctly set to false when applied to a class type with a deleted or private copy constructor.

    A questa modifica non è associata alcuna diagnostica del compilatore.There is no compiler diagnostic associated with this change.

    EsempioExample

    #include <type_traits>  
    
    class X1  
    {  
    public:  
        X1(const X1&) = delete;  
    };  
    
    class X2  
    {  
    private:  
        X2(const X2&);  
    };  
    
    static_assert(std::is_convertible<X1&, X1>::value, "BOOM");static_assert(std::is_convertible<X2&, X2>::value, "BOOM");  
    

    Nelle versioni precedenti di Visual C++, le asserzioni statiche nella parte inferiore di questo esempio passano perché std::is_convertable<>::value è stato impostato erroneamente su true.In previous versions of Visual C++, the static assertions at the bottom of this example pass because std::is_convertable<>::value was incorrectly set to true. Ora std::is_convertable<>::value è impostato correttamente su false causando l'esito negativo delle asserzioni statiche.Now, std::is_convertable<>::value is correctly set to false, causing the static assertions to fail.

  • I costruttori di copia e di spostamento semplici impostati come predefiniti o eliminati rispettano gli identificatori di accessoDefaulted or deleted trivial copy and move constructors respect access specifiers

    Le versioni precedenti del compilatore non verificavano l'identificatore di accesso dei costruttori di copia o spostamento semplici impostati come predefiniti o eliminati prima di consentirne la chiamata.Previous versions of the compiler did not check the access specifier of defaulted or deleted trivial copy and move constructors before allowing them to be called. Questo comportamento precedente non era corretto e non è conforme allo standard C++.This old behavior was incorrect and does not conform to the C++ standard. In alcuni casi questo comportamento creava un rischio di generazione di codice errato senza avvisare, determinando un comportamento imprevedibile in fase di esecuzione.In some cases, this old behavior created a risk of silent bad code generation, resulting in unpredictable runtime behavior. Il compilatore ora controlla l'identificatore di accesso dei costruttori di copia e spostamento semplici impostati come predefiniti o eliminati per determinare se può essere effettuata la chiamata e, se non è possibile, genera un avviso del compilatore C2248 di conseguenza.The compiler now checks the access specifier of defaulted or deleted trivial copy and move constructors to determine whether it can be called, and if not, issues compiler warning C2248 as a result.

    error C2248: 'S::S' cannot access private member declared in class 'S'  
    

    Esempio (prima)Example (before)

    class S {  
    public:  
           S() = default;  
    private:  
        S(const S&) = default;  
    };  
    
    void f(S);  // pass S by value  
    
    int main()  
    {  
        S s;  
        f(s);  // error C2248, can't invoke private copy constructor  
    }  
    

    Esempio (dopo)Example (after)

    class S {  
    public:  
           S() = default;  
    private:  
        S(const S&) = default;  
    };  
    
    void f(const S&);  // pass S by reference  
    
    int main()  
    {  
        S s;  
        f(s);  
    }  
    
  • Deprecazione del supporto per il codice ATL con attributi (livello 1 (/W1) attivo per impostazione predefinita)Deprecation of attributed ATL code support (Level 1 (/W1) on-by-default)

    Le versioni precedenti del compilatore supportavano il codice ATL con attributi.Previous versions of the compiler supported attributed ATL code. Come fase successiva della rimozione del supporto per il codice ATL con attributi avviata in Visual C++ 2008, il codice ATL con attributi è stato deprecato.As the next phase of removing support for attributed ATL code that began in Visual C++ 2008, attributed ATL code has been deprecated. Ora il compilatore genera l'avviso C4467 per consentire l'identificazione di questo tipo di codice deprecato.The compiler now issues compiler warning C4467 to help identify this kind of deprecated code.

    warning C4467: Usage of ATL attributes is deprecated  
    

    Per continuare a usare codice ATL con attributi finché il supporto viene rimosso dal compilatore, è possibile disabilitare questo avviso passando gli argomenti /Wv:18 o /wd4467 della riga di comando al compilatore o aggiungendo #pragma warning(disable:4467) nel codice sorgente.If you want to continue using attributed ATL code until support is removed from the compiler, you can disable this warning by passing the /Wv:18 or /wd4467 command line arguments to the compiler, or by adding #pragma warning(disable:4467) in your source code.

    Esempio 1 (prima)Example 1 (before)

              [uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")]  
    class A {};  
    

    Esempio 1 (dopo)Example 1 (after)

    __declspec(uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")) A {};  
    

    In alcuni casi potrebbe essere necessario o preferibile creare un file IDL file per evitare l'uso degli attributi ATL deprecati, come nell'esempio di codice riportato di seguitoSometimes you might need or want to create an IDL file to avoid the use deprecated ATL attributes, as in the example code below

    Esempio 2 (prima)Example 2 (before)

    [emitidl];  
    [module(name="Foo")];  
    
    [object, local, uuid("9e66a290-4365-11d2-a997-00c04fa37ddb")]  
    __interface ICustom {  
        HRESULT Custom([in] long l, [out, retval] long *pLong);  
        [local] HRESULT CustomLocal([in] long l, [out, retval] long *pLong);  
    };  
    
    [coclass, appobject, uuid("9e66a294-4365-11d2-a997-00c04fa37ddb")]  
    class CFoo : public ICustom  
    {  
        // ...  
    };  
    

    Per prima cosa creare il file *.idl. Il file vc140.idl generato può essere usato per ottenere un file *.idl contenente le interfacce e le annotazioni.First, create the *.idl file; the vc140.idl generated file can be used to obtain an *.idl file containing the interfaces and annotations.

    Quindi, aggiungere una fase MIDL alla compilazione per assicurarsi che le definizioni dell'interfaccia di C++ vengano generate.Next, add a MIDL step to your build to make sure that the C++ interface definitions are generated.

    Esempio 2 IDL (dopo)Example 2 IDL (after)

    import "docobj.idl";  
    
    [  
        object,local,uuid(9e66a290-4365-11d2-a997-00c04fa37ddb)  
    ]  
    
    interface ICustom : IUnknown {  
        HRESULT  Custom([in] long l, [out,retval] long *pLong);  
        [local] HRESULT  CustomLocal([in] long l, [out,retval] long *pLong);  
    };  
    
    [ version(1.0), uuid(29079a2c-5f3f-3325-99a1-3ec9c40988bb) ]  
    library Foo  
    {  
        importlib("stdole2.tlb");  
        importlib("olepro32.dll");  
            [  
                version(1.0),  
                appobject,uuid(9e66a294-4365-11d2-a997-00c04fa37ddb)  
            ]  
    
        coclass CFoo {  
            interface ICustom;  
        };  
    }  
    

    Usare quindi ATL direttamente nel file di implementazione, come illustrato nell'esempio di codice che segue.Then, use ATL directly in the implementation file, as in the example code below.

    Esempio 2 Implementazione (dopo)Example 2 Implementation (after)

    #include <idl.header.h>  
    #include <atlbase.h>  
    
    class ATL_NO_VTABLE CFooImpl :  
        public ICustom,  
        public ATL::CComObjectRootEx<CComMultiThreadModel>  
    {  
    public:  
        BEGIN_COM_MAP(CFooImpl)  
        COM_INTERFACE_ENTRY(ICustom)  
        END_COM_MAP()  
    };  
    
  • File di intestazione precompilata (PCH) e direttive #include non corrispondenti (interessa solo /Wall /WX)Precompiled header (PCH) files and mismatched #include directives (only affects /Wall /WX)

    Le versioni precedenti del compilatore accettavano le direttive #include non corrispondenti nei file di origine tra le compilazioni -Yc e -Yu quando venivano usati file di intestazione precompilata (PCH).Previous versions of the compiler accepted mismatched #include directives in source files between -Yc and -Yu compilations when using precompiled header (PCH) files. Il codice scritto in questo modo non è più accettato dal compilatore.Code written in this way is no longer accepted by the compiler. Il compilatore ora genera un avviso CC4598 per consentire l'identificazione delle direttive #include non corrispondenti quando si usano i file PCH.The compiler now issues compiler warning CC4598 to help identify mismatched #include directives when using PCH files.

    warning C4598: 'b.h': included header file specified for Ycc.h at position 2 does not match Yuc.h at that position  
    

    Esempio (prima):Example (before):

    X.cpp (-Ycc.h)X.cpp (-Ycc.h)

    #include "a.h"  
    #include "b.h"  
    #include "c.h"  
    

    Z.cpp (-Yuc.h)Z.cpp (-Yuc.h)

    #include "b.h"  
    #include "a.h"  // mismatched order relative to X.cpp  
    #include "c.h"  
    

    Esempio (dopo)Example (after)

    X.cpp (-Ycc.h)X.cpp (-Ycc.h)

    #include "a.h"  
    #include "b.h"   
    #include "c.h"  
    

    Z.cpp (-Yuc.h)Z.cpp (-Yuc.h)

    #include "a.h"  
    #include "b.h" // matched order relative to X.cpp  
    #include "c.h"  
    
  • File di intestazione precompilata (PCH) e directory di inclusione non corrispondenti (interessa solo /Wall /WX)Precompiled header (PCH) files and mismatched include directories (only affects /Wall /WX)

    Le versioni precedenti del compilatore accettavano gli argomenti della riga di comando delle directory di inclusione non corrispondenti (-I) per il compilatore tra le compilazioni -Yc e -Yu quando venivano usati file di intestazione precompilata (PCH).Previous versions of the compiler accepted mismatched include directory (-I) command line arguments to the compiler between -Yc and -Yu compilations when using precompiled header (PCH) files. Il codice scritto in questo modo non è più accettato dal compilatore.Code written in this way is no longer accepted by the compiler. Il compilatore ora genera un avviso CC4599 per consentire l'identificazione degli argomenti della riga di comando delle directory di inclusione non corrispondenti (-I) quando si usano i file PCH.The compiler now issues compiler warning CC4599 to help identify mismatched include directory (-I) command line arguments when using PCH files.

    warning C4599: '-I..' : specified for Ycc.h at position 1 does not match Yuc.h at that position  
    

    Esempio (prima)Example (before)

    cl /c /Wall /Ycc.h -I.. X.cpp  
    cl /c /Wall /Yuc.h Z.cpp  
    

    Esempio (dopo)Example (after)

    cl /c /Wall /Ycc.h -I.. X.cpp  
    cl /c /Wall /Yuc.h -I.. Z.cpp