Dela via


Ändringshistorik för Microsoft C/C++ 2003 –2015

Den här artikeln beskriver alla brytande ändringar i Visual Studio från 2015 ända tillbaka till 2003, och här refererar termerna "nytt beteende" eller "nu" till Visual Studio 2015 och senare. Termerna "old behavior" och "before" refererar till Visual Studio 2013 och tidigare versioner.

Information om den senaste versionen av Visual Studio finns i Nyheter för C++ i Visual Studio och C++-efterlevnadsförbättringar i Visual Studio.

Anmärkning

Det finns inga binära ändringar som bryter kompatibilitet mellan Visual Studio 2015 och Visual Studio 2017.

När du uppgraderar till en ny version av Visual Studio kan det uppstå kompilerings- och/eller körningsfel i kod som tidigare kompilerats och körts korrekt. Ändringar i den nya versionen som orsakar sådana problem kallas icke-bakåtkompatibla ändringar, och vanligtvis krävs de av ändringar i C++-språkstandarden, funktionssignaturer eller layouten för objekt i minnet.

För att undvika körningsfel som är svåra att identifiera och diagnostisera rekommenderar vi att du aldrig statiskt länkar till binärfiler som kompilerats med hjälp av en annan version av kompilatorn. När du uppgraderar ett EXE- eller DLL-projekt måste du också uppgradera de bibliotek som det länkar till. Skicka inte CRT-typer (C Runtime) eller C++ Standard Library (C++ Standard Library) mellan binärfiler, inklusive DLL:er, som kompilerats med hjälp av olika versioner av kompilatorn. Mer information finns i Potentiella fel som skickar CRT-objekt över DLL-gränser.

Du bör aldrig skriva kod som är beroende av en viss layout för ett objekt som inte är ett COM-gränssnitt eller ett POD-objekt. Om du skriver sådan kod måste du se till att den fungerar efter uppgraderingen. Mer information finns i Portabilitet vid ABI-gränser.

Dessutom kan pågående förbättringar av kompilatorns efterlevnad ibland ändra hur kompilatorn förstår din befintliga källkod. Du kan till exempel hitta nya eller olika fel under bygget, eller till och med beteendeskillnader i kod som tidigare skapats och som verkade köras korrekt. Även om dessa förbättringar inte bryter mot ändringar som de som beskrivs i det här dokumentet, kan du behöva göra ändringar i källkoden för att lösa följande problem:

Ändringar i Visual Studio 2015-överensstämmelse

C Runtime Library (CRT)

Allmänna ändringar

  • Omstrukturerade binärfiler

    CRT-biblioteket har omstrukturerats till två olika binärfiler: en Universell CRT (ucrtbase), som innehåller de flesta standardfunktionerna och ett VC Runtime-bibliotek (vcruntime). vcruntime-biblioteket innehåller kompilatorrelaterade funktioner som undantagshantering och inbyggda funktioner. Om du använder standardinställningarna för projekt påverkar inte den här ändringen dig eftersom länkaren använder de nya standardbiblioteken automatiskt. Om du har angett projektets Linker-egenskapIgnorera alla standardbibliotek till Ja eller om du använder /NODEFAULTLIB alternativet länkare på kommandoraden måste du uppdatera listan med bibliotek (i egenskapen Ytterligare beroenden ) för att inkludera de nya, omstrukturerade biblioteken. Ersätt det gamla CRT-biblioteket (libcmt.lib, libcmtd.lib, msvcrt.lib, msvcrtd.lib) med motsvarande omstrukturerade bibliotek. För vart och ett av de två omstrukturerade biblioteken finns det statiska (.lib) och dynamiska (.dll) versioner, samt releaseversioner (utan suffix) och felsökningsversioner (med suffixet "d"). De dynamiska versionerna har ett importbibliotek som du länkar till. De två omstrukturerade biblioteken är Universal CRT, särskilt ucrtbase.dll eller ucrtbase.lib, ucrtbased.dll eller ucrtbased.lib och VC-körningsbiblioteket, libvcruntime.lib,vcruntime-versionen.dll, libvcruntimed.liboch vcruntimed-versionen.dll. Versionen i både Visual Studio 2015 och Visual Studio 2017 är 140. Se CRT-biblioteksfunktioner.

<locale.h>

  • localeconv

    Funktionen localeconv som deklareras i locale.h fungerar nu korrekt när språkvarianten per tråd är aktiverad. I tidigare versioner av biblioteket returnerade funktionen lconv data för den globala locale:n, inte trådens locale.

    Om du använder nationella inställningar per tråd bör du kontrollera din användning av localeconv. Om koden förutsätter att de lconv data som returneras är för det globala språket bör du korrigera dem.

<math.h>

  • C++ överlagringar av matematiska biblioteksfunktioner

    I tidigare versioner <math.h> definierade vissa, men inte alla, C++-överlagringar för matematiska biblioteksfunktioner. Resten av överbelastningarna fanns i den <cmath> rubriken. Kod som endast innehåller <math.h> kan få problem med funktionsöverlagringslösning. Nu har C++-överlagringarna tagits bort från <math.h> och finns bara i <cmath>.

    Lös fel genom att inkludera <cmath> för att hämta deklarationerna för de funktioner som har tagits bort från <math.h>. Dessa funktioner har flyttats:

    • double abs(double) och float abs(float)
    • double pow(double, int), float pow(float, float), float pow(float, int), , , long double pow(long double, long double)long double pow(long double, int)
    • float och long double versioner av flyttalsfunktioner acos, acosh, asin, asinh, atan, atanh, atan2, cbrt, ceil, copysign, cos, cosh, erf, erfc, exp, exp2, expm1, fabs, fdim, floor, fma, fmax, fmin, fmod, frexp, hypot, ilogb, ldexp, lgamma, llrint, llround, log, log10, log1p, log2, lrint, lround, modf, nearbyint, nextafter, nexttoward, remainder, remquo, rint, round, scalbln, scalbn, sin, sinh, sqrt, tan, tanh, tgamma och trunc

    Om du har kod som använder abs med en flyttalstyp som bara innehåller <math.h> rubriken, kommer flyttalsversionerna inte längre att vara tillgängliga. Anropet löser sig nu till abs(int), även med ett flyttalsargument, vilket genererar felet:

    warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of data
    

    Korrigeringen för den här varningen är att ersätta anropet till abs med en flyttalsversion av abs, till exempel fabs för ett dubbelargument eller fabsf för ett flyttalargument, eller inkludera <cmath> huvudfilen och fortsätta att använda abs.

  • Flyttalsöverensstämmelse

    Många ändringar i matematikbiblioteket har gjorts för att förbättra överensstämmelsen med specifikationerna för IEEE-754 och C11 bilaga F med avseende på specialfallsindata som NaN och infinities. Till exempel behandlas tysta NaN-indata, som ofta behandlades som fel i tidigare versioner av biblioteket, inte längre som fel. Se IEEE 754 Standard och bilaga F till C11-standarden.

    Dessa ändringar orsakar inte kompileringsfel, men kan leda till att program fungerar annorlunda och mer korrekt enligt standarden.

  • FLT_ROUNDS

    I Visual Studio 2013 expanderade FLT_ROUNDS makrot till ett konstant uttryck, vilket var felaktigt eftersom avrundningsläget kan konfigureras vid körning, till exempel genom att anropa fesetround. Det FLT_ROUNDS makrot är nu dynamiskt och återspeglar det aktuella avrundningsläget korrekt.

<new> och <new.h>

  • new och delete

    I tidigare versioner av biblioteket exporterades de implementeringsdefinierade 'new' och 'delete'-operatorfunktionerna från körningsbibliotekets DLL (till exempel msvcr120.dll). Dessa operatorfunktioner är nu alltid statiskt länkade till dina binärfiler, även när du använder DLL:er för körningsbiblioteket.

    Detta är ingen brytande förändring för native eller blandad kod (/clr), men för kod som kompileras som /clr:pure kan denna ändring göra att din kod misslyckas med att kompilera. Om du kompilerar kod som /clr:pure, kan du behöva lägga till #include <new> eller #include <new.h> för att kringgå byggfel på grund av den här ändringen. Alternativet/clr:pure är inaktuellt i Visual Studio 2015 och stöds inte i Visual Studio 2017. Kod som måste vara "ren" ska portas till C#.

<process.h>

  • _beginthread och _beginthreadex

    Funktionerna _beginthread och _beginthreadex innehåller nu en referens till modulen där trådproceduren definieras under trådens varaktighet. Detta hjälper till att säkerställa att modulerna inte avlastas förrän en tråd har körts färdig.

<stdarg.h>

  • va_start och referenstyper

    När du kompilerar C++-kod va_start verifierar du nu vid kompileringstiden att argumentet som skickas till den inte är av referenstyp. Argument av referenstyp är förbjudna enligt C++ Standard.

<stdio.h> och <conio.h>

  • Printf- och scanf-funktionsfamiljen definieras nu inline.

    Definitionerna för alla funktionerna printf och scanf har placerats inline i <stdio.h>, <conio.h>, och andra CRT-huvuden. Den här icke-bakåtkompatibla ändringen leder till ett länkfel (LNK2019, olösta externa symboler) för alla program som deklarerade dessa funktioner lokalt utan att inkludera lämpliga CRT-huvudfiler. Om det är möjligt bör du uppdatera koden så att den innehåller CRT-huvudena (d.v.s. lägg till #include <stdio.h>) och infogade funktioner, men om du inte vill ändra koden så att den innehåller dessa huvudfiler är en alternativ lösning att lägga legacy_stdio_definitions.lib till i dina länkningsindata.

    Om du vill lägga till det här biblioteket i länkningsindata i IDE öppnar du snabbmenyn för projektnoden, väljer Egenskaper. I dialogrutan Projektegenskaper väljer du Länka och redigerar Linker-indata för att lägga legacy_stdio_definitions.lib till i den semikolonavgränsade listan.

    Om projektet länkar till statiska bibliotek som kompilerats med en version av Visual Studio tidigare än 2015 kan länkaren rapportera en olöst extern symbol. Dessa fel kan referera till interna definitioner för _iob, _iob_funceller relaterade importer för vissa <stdio.h> funktioner i form av imp*. Microsoft rekommenderar att du kompilerar om alla statiska bibliotek med den senaste versionen av C++-kompilatorn och biblioteken när du uppgraderar ett projekt. Om biblioteket är ett bibliotek från tredje part för vilket källan inte är tillgänglig bör du antingen begära en uppdaterad binärfil från tredje part eller kapsla in din användning av biblioteket i en separat DLL som du kompilerar med den äldre versionen av kompilatorn och biblioteken.

    Varning

    Om du länkar till Windows SDK 8.1 eller tidigare kan det uppstå dessa olösta externa symbolfel. I så fall bör du lösa felet genom att lägga till legacy_stdio_definitions.lib i länkningsindata enligt beskrivningen tidigare.

    Om du vill felsöka olösta symbolfel kan du prova att använda dumpbin.exe för att undersöka de symboler som definierats i en binär fil. Prova följande kommandorad för att visa symboler som definierats i ett bibliotek.

    dumpbin.exe /LINKERMEMBER somelibrary.lib
    
  • hämtar och _getws

    Funktionerna hämtar och _getws har tagits bort. Funktionen gets har tagits bort från C Standard Library i C11 eftersom den inte kan användas på ett säkert sätt. Funktionen _getws var ett Microsoft-tillägg som var likvärdigt med gets men för bredsträngar. Som alternativ till dessa funktioner bör du överväga att använda fgets, fgetws, gets_s och _getws_s.

  • _cgets och _cgetws

    Funktionerna _cgets och _cgetws har tagits bort. Som alternativ till dessa funktioner bör du överväga att använda _cgets_s och _cgetws_s.

  • Oändlighet och NaN-formatering

    I tidigare versioner skulle infinities och NaN formateras med hjälp av en uppsättning MSVC-specifika sentinel-strängar.

    • Oändlighet: 1.#INF

    • Tyst NaN: 1.#QNAN

    • Signalerar NaN: 1.#SNAN

    • Obestämd NaN: 1.#IND

    Något av dessa format kan ha prefixats av ett tecken och kan ha formaterats något annorlunda beroende på fältbredd och precision (ibland med ovanliga effekter skulle till exempel printf("%.2f\n", INFINITY) skriva ut 1.#J eftersom #INF skulle "avrundas" till en 2-siffrig precision). C99 införde nya krav på hur infinities och NaN ska formateras. MSVC-implementeringen uppfyller nu dessa krav. De nya strängarna är följande:

    • Oändlighet: inf

    • Tyst NaN: nan

    • Signalerande NaN: nan(snan)

    • Obestämd NaN: nan(ind)

    Något av dessa kan föregås av ett tecken. Om en formatspecificerare med versaler används (%F i stället för %f) skrivs strängarna ut med versaler (INF i stället för inf), enligt vad som krävs.

    scanf-funktionerna har ändrats för att parsa dessa nya strängar, så att dessa strängar nu gör en återresa genom printf och scanf.

  • Flyttalsformatering och parsning

    Ny flyttalsformatering och parsningsalgoritmer har introducerats för att förbättra korrektheten. Den här ändringen påverkar utskrifts- och skanningsfamiljerna för funktioner och funktioner som strtod.

    De gamla formateringsalgoritmerna skulle bara generera ett begränsat antal siffror och skulle sedan fylla de återstående decimalerna med noll. De kan vanligtvis generera strängar som går tillbaka till det ursprungliga flyttalvärdet, men som inte är bra om du vill ha det exakta värdet (eller den närmaste decimalrepresentationen av det). De nya formateringsalgoritmerna genererar så många siffror som krävs för att representera värdet (eller för att fylla den angivna precisionen). Som ett exempel på förbättringen: överväg resultatet när du skriver ut en stor kraft av två.

    printf("%.0f\n", pow(2.0, 80))
    

    Gamla utdata:

    1208925819614629200000000
    

    Nya utdata:

    1208925819614629174706176
    

    De gamla parsningsalgoritmerna skulle endast överväga upp till 17 signifikanta siffror från indatasträngen och ta bort resten av siffrorna. Den här metoden räcker för att generera en nära uppskattning av värdet som representeras av strängen, och resultatet är vanligtvis mycket nära det korrekt avrundade resultatet. Den nya implementeringen tar hänsyn till alla nuvarande siffror och ger ett korrekt avrundat resultat för alla indata (upp till 768 siffror långa). Dessutom respekterar dessa funktioner nu avrundningsläget (vilket kan styras med hjälp av fesetround). Detta kan vara en icke-bakåtkompatibel beteendeförändring eftersom dessa funktioner kan ge olika resultat. De nya resultaten är alltid mer korrekta än de gamla resultaten.

  • Hexadecimal och oändlighet/NaN-flyttal parsning

    Algoritmerna för parsning av flyttal kommer nu att parsa hexadecimala flyttalssträngar (till exempel de som genereras av %a och %A printf-formatspecifikatorer) och alla oändlighet- och NaN-strängar som genereras av printf-funktionerna, såsom beskrivet ovan.

  • %A och %a noll utfyllnad

    Formatspecificerarna %a och %A formaterar ett flyttalsnummer som hexadecimal mantissa och binär exponent. I tidigare versioner printf häftade funktionerna felaktigt strängar med nollor. Till exempel skulle printf("%07.0a\n", 1.0) skriva ut 00x1p+0, där det ska bli 0x01p+0. Den här bristen har åtgärdats.

  • %A- och %a-noggrannhet

    Standardprecisionen för %A och %a formatspecificerare var 6 i tidigare versioner av biblioteket. Standardprecisionen är nu 13 för överensstämmelse med C Standard.

    Det här är en körningsbeteendeändring i utdata för alla funktioner som använder en formatsträng med %A eller %a. I det gamla beteendet kan utdata som använder %A-specificeraren vara "1.1A2B3Cp+111". Nu är utdata för samma värde "1.1A2B3C4D5E6F7p+111". För att få det gamla beteendet kan du ange precisionen, till exempel %.6A. Se Precisionsspecifikation.

  • %F-specifier

    Nu stöds %F format- och konverteringsspecifierare. Det är funktionellt likvärdigt med formatspecificeraren %f, förutom att oändligheter och NaN formateras med versaler.

    I tidigare versioner användes implementeringen för att parsa F och N som längdmodifierare. Det här beteendet dateras tillbaka till åldern för segmenterade adressutrymmen: dessa längdmodifierare användes för att indikera långt respektive nära pekare, som i %Fp eller %Ns. Det här beteendet har tagits bort. Om %F påträffas behandlas den nu som %F formatspecificerare. Om %N påträffas behandlas den nu som en ogiltig parameter.

  • Exponentformatering

    Formatspecificerarna %e och %E formaterar ett flyttalsnummer som decimalmantissa och exponent. De %g- och %G- formatkoderna formaterar även tal i detta format i vissa fall. I tidigare versioner skulle CRT alltid generera strängar med tresiffriga exponenter. Skulle till exempel printf("%e\n", 1.0) skriva ut 1.000000e+000, vilket var felaktigt. C kräver att om exponenten endast kan representeras med en eller två siffror ska endast två siffror skrivas ut.

    I Visual Studio 2005 lades en global överensstämmelseväxel till: _set_output_format. Ett program kan anropa den här funktionen med argumentet _TWO_DIGIT_EXPONENT för att aktivera överensstämmande exponentutskrifter. Standardbeteendet har ändrats till standardkonform exponentutskriftsläge.

  • Validering av formatsträng

    I tidigare versioner skulle funktionerna printf och scanf tyst acceptera många ogiltiga formatsträngar, ibland med ovanliga effekter. Till exempel skulle %hlhlhld behandlas som %d. Alla ogiltiga formatsträngar behandlas nu som ogiltiga parametrar.

  • strängvalidering i fopenläge

    I tidigare versioner accepterade funktionsfamiljen fopen tyst vissa ogiltiga lägessträngar, till exempel r+b+. Ogiltiga lägessträngar identifieras nu och behandlas som ogiltiga parametrar.

  • _O_U8TEXT-läge

    Funktionen _setmode rapporterar nu korrekt läge för strömmar som öppnats i O_U8TEXT-läge. I tidigare versioner av biblioteket skulle det rapportera sådana strömmar som öppnas i _O_WTEXT.

    Det här är en avbrottsförändring om din kod tolkar _O_WTEXT-läget för strömmar där kodningen är UTF-8. Om programmet inte stöder UTF_8 kan du överväga att lägga till stöd för den här allt vanligare kodningen.

  • snprintf och vsnprintf

    Funktionerna snprintf och vsnprintf implementeras nu. Äldre kod gav ofta definitioner av makroversioner av dessa funktioner eftersom de inte implementerades av CRT-biblioteket, men de behövs inte längre i nyare versioner. Om snprintf eller vsnprintf definieras som ett makro innan du inkluderar <stdio.h>misslyckas kompilering nu med ett fel som anger var makrot har definierats.

    Normalt är korrigeringen av det här problemet att ta bort eventuella deklarationer av snprintf eller vsnprintf i användarkod.

  • tmpnam genererar användbara filnamn

    I tidigare versioner genererade funktionerna tmpnam och tmpnam_s filnamn i roten på enheten (till exempel \sd3c.). Dessa funktioner genererar nu användbara filnamnssökvägar i en tillfällig katalog.

  • Filinkapsling

    I tidigare versioner definierades den fullständiga FILtypen offentligt i <stdio.h>, så det var möjligt för användarkod att nå till en FIL och ändra dess interna. Biblioteket har ändrats för att dölja implementeringsinformation. Som en del av den här ändringen är FIL enligt definitionen i <stdio.h> nu en ogenomskinlig typ och dess medlemmar är otillgängliga utanför själva CRT.

  • _outp och _inp

    Funktionerna _outp, _outpw, _outpd, _inp, _inpw och _inpd har tagits bort.

<stdlib.h>, <malloc.h> och <sys/stat.h>

  • strtof och wcstof

    Funktionerna strtof och wcstof kunde inte anges errno till ERANGE när värdet inte kunde representeras som en flyttal. Det här felet var specifikt för dessa två funktioner. funktionerna strtod, wcstod, strtoldoch wcstold påverkades inte. Det här problemet har åtgärdats och är en icke-bakåtkompatibel ändring.

  • Justerade allokeringsfunktioner

    I tidigare versioner skulle de justerade allokeringsfunktionerna (_aligned_malloc, _aligned_offset_mallocosv.) tyst acceptera begäranden om ett block med justeringen 0. Den begärda justeringen måste vara en potens av två, vilket inte gäller för noll. En begärd justering av 0 behandlas nu som en ogiltig parameter. Det här problemet har åtgärdats och är en icke-bakåtkompatibel ändring.

  • Heap-funktioner

    Funktionerna _heapadd, _heapsetoch _heapused har tagits bort. Dessa funktioner har varit icke fungerande sedan CRT uppdaterades för att använda Windows-heapen.

  • smallheap

    Länkalternativet smallheap har tagits bort. Se Länkalternativ.

  • _stat

    Serien _stat med funktioner används CreateFile i Visual Studio 2015, i stället för FindFirstFile som i Visual Studio 2013 och tidigare. Det innebär att _stat på en sökväg som slutar med ett snedstreck lyckas om sökvägen refererar till en katalog, till skillnad från tidigare när funktionen skulle fel med errno inställt på ENOENT.

<string.h>

  • wcstok

    Funktionens wcstok signatur har ändrats för att matcha vad som krävs av C Standard. I tidigare versioner av biblioteket var signaturen för den här funktionen:

    wchar_t* wcstok(wchar_t*, wchar_t const*)
    

    Den använde en intern kontext per tråd för att spåra tillstånd mellan anrop, vilket är gjort för strtok. Funktionen har nu signaturen wchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**)och kräver att anroparen skickar kontexten som ett tredje argument till funktionen.

    En ny _wcstok funktion har lagts till med den gamla signaturen för att underlätta porteringen. När du kompilerar C++-kod finns det också en intern överlagring av wcstok som har den gamla signaturen. Den här överlagringen deklareras som inaktuell. I C-kod kan du definiera define_CRT_NON_CONFORMING_WCSTOK för att orsaka att _wcstok används i stället för wcstok.

<time.h>

  • klocka

    I tidigare versioner clock implementerades funktionen med hjälp av Windows API GetSystemTimeAsFileTime. Med den här implementeringen var klockfunktionen känslig för systemtiden och var därför inte nödvändigtvis monoton. Klockfunktionen har omimplementerats i termer av QueryPerformanceCounter och är nu monoton.

  • fstat och _utime

    I tidigare versioner hanterar funktionerna _stat, fstat och _utime sommartid felaktigt. Före Visual Studio 2013 justerade alla dessa funktioner felaktigt standardtidstiderna som om de befann sig i dagsljus.

    I Visual Studio 2013 har problemet åtgärdats i funktionsfamiljen _stat , men liknande problem i funktionsfamiljerna fstat och _utime har inte åtgärdats. Den här partiella korrigeringen ledde till problem på grund av inkonsekvensen mellan funktionerna. fstat- och _utime-funktionernas familjer har nu åtgärdats, så alla dessa funktioner hanterar sommartid korrekt och konsekvent.

  • asctime

    I tidigare versioner skulle funktionen asctime fylla på ensiffriga dagar med en inledande nolla, till exempel: Fri Jun 06 08:00:00 2014. Specifikationen kräver att sådana dagar fylls med ett inledande mellanslag, som i Fri Jun 6 08:00:00 2014. Det här problemet har åtgärdats.

  • strftime och wcsftime

    Funktionerna strftime och wcsftime stöder nu formatspecificerarna %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %uoch %V format. Dessutom parsas E- och O-modifierarna men ignoreras.

    Den %c formatsspecifikatorn anges som att producera en "lämplig datum- och tidsrepresentation" för den aktuella orten. I C-språkinställningen måste den här representationen vara samma som %a %b %e %T %Y, samma form som produceras av asctime. I tidigare versioner har %c formatspecificeraren felaktigt formaterat tider med en MM/DD/YY HH:MM:SS representation. Det här problemet har åtgärdats.

  • timespec och TIME_UTC

    <time.h>-huvudet definierar nu timespec-typen och timespec_get-funktionen från C11-standard. Dessutom har det TIME_UTC makrot definierats för användning med timespec_get funktionen. Den här uppdateringen är en icke-bakåtkompatibel ändring för kod som har en motstridig definition för någon av dessa identifierare.

  • CLOCKS_PER_SEC

    Det CLOCKS_PER_SEC makrot expanderas nu till ett heltal av typen clock_t, vilket krävs av C-språket.

C++-standardbibliotek

För att aktivera nya optimeringar och felsökningskontroller bryter Visual Studio-implementeringen av C++-standardbiblioteket avsiktligt binär kompatibilitet från en version till en annan. När C++-standardbiblioteket används kan därför objektfiler och statiska bibliotek som kompileras med hjälp av olika versioner inte blandas i en binär fil (EXE eller DLL) och C++ Standard Library-objekt kan inte skickas mellan binärfiler som kompileras med hjälp av olika versioner. Sådan blandning genererar länkfel om _MSC_VER matchningar. (_MSC_VER är makrot som innehåller kompilatorns huvudversion, till exempel 1800 för Visual Studio 2013.) Den här kontrollen kan inte identifiera DLL-blandning och kan inte identifiera blandning som omfattar Visual Studio 2008 eller tidigare.

  • C++ Standard Library innehåller filer

    Vissa ändringar har gjorts i inkluderingsstrukturen i C++-standardbiblioteksrubrikerna. C++ standardbibliotekets huvudfiler tillåts inkludera varandra på ospecificerade sätt. I allmänhet bör du skriva din kod så att den noggrant innehåller alla rubriker som den behöver enligt C++-standarden och inte förlitar sig på vilka C++ Standard Library-huvuden som innehåller andra C++ Standard Library-huvuden. Detta gör koden portabel mellan versioner och plattformar. Minst två sidhuvudändringar i Visual Studio 2015 påverkar användarkoden. För det första, <string> innehåller inte längre <iterator>. För det andra deklarerar <tuple> nu utan att inkludera alla std::array, vilket kan leda till kodbrott genom följande kombination av kodkonstruktioner: din kod har en variabel med namnet "array", och du har ett användningsdirektiv "using namespace std;", och du inkluderar en C++ Standard Library-rubrik (till exempel <array>) som innehåller <functional>, som nu deklarerar <tuple>.

  • steady_clock

    Implementeringen <chrono> av steady_clock har ändrats för att uppfylla C++ Standard-kraven för stabilitet och monotonitet. steady_clock är nu baserad på QueryPerformanceCounter och high_resolution_clock är nu en typedef för steady_clock. Därför är i Visual Studio steady_clock::time_point nu en typedef för chrono::time_point<steady_clock>, men detta är inte nödvändigtvis fallet för andra implementeringar.

  • allokerare och konstanter

    Vi kräver nu jämförelse av allokeringsjämlikhet/ojämlikhet för att acceptera const-argument på båda sidor. Om dina allokerare definierar dessa operatorer så här,

    bool operator==(const MyAlloc& other)
    

    sedan bör du uppdatera dem och deklarera dem som const-medlemmar:

    bool operator==(const MyAlloc& other) const
    
  • const-element

    C++-standarden har alltid förbjudna containrar med const-element (till exempel vector<const T> eller set<const T>). Visual Studio 2013 och tidigare accepterade sådana containrar. I den aktuella versionen kan sådana containrar inte kompileras.

  • std::allocator::d eallocate

    I Visual Studio 2013 och tidigare ignorerades argumentet som skickades in för std::allocator::deallocate(p, n). C++-standarden har alltid krävt att n måste vara lika med det värde som skickas som det första argumentet till anropet av allocate, som returnerade p. I den aktuella versionen inspekteras dock värdet för n . Kod som skickar argument för n som skiljer sig från vad standarden kräver kan krascha vid körning.

  • hash_map och hash_set

    Huvudfilerna <hash_map> som inte är standard och <hash_set> är inaktuella i Visual Studio 2015 och tas bort i en framtida version. Använd <unordered_map> och <unordered_set> i stället.

  • komparatorer och operator()

    Associativa containrar ( <map> familjen) kräver nu att deras jämförelseobjekt har anropsbara funktionsanropsoperatorer. Följande kod i en jämförelseklassdeklaration kan nu inte kompileras:

    bool operator()(const X& a, const X& b)
    

    Lös det här felet genom att ändra funktionsdeklarationen till:

    bool operator()(const X& a, const X& b) const
    
  • typegenskaper

    De gamla namnen för typegenskaper från en tidigare version av C++-utkaststandarden har tagits bort. Dessa ändrades i C++11 och har uppdaterats till C++11-värdena i Visual Studio 2015. I följande tabell visas de gamla och nya namnen.

    Gammalt namn Nytt namn
    lägg_till_referens add_lvalue_reference
    har_standardkonstruktor is_default_konstruerbar
    har_kopieringskonstruktor är_kopierings_konstruerbar
    har_move_constructor är_konstruerbar_vid_överföring
    har_ingen_undantagskonstruktor is_nothrow_default_constructible
    has_nothrow_default_constructor (har standardkonstruktor utan undantag) is_nothrow_default_constructible
    har_kopiering_utan_undantag is_nothrow_copy_constructible
    har_nothrow_kopieringskonstruktor is_nothrow_copy_constructible
    har_nothrow_move_konstruktör is_nothrow_move_constructible
    has_nothrow_assign is_nothrow_copy_assignable
    has_nothrow_copy_assign is_no_throw_copy_assignable (kan kopieras utan undantag)
    har_ingen_undantags_flytt_tilldelning Det är lämpligt att behålla "is_nothrow_move_assignable" i sin ursprungliga form för att säkerställa att den förstås korrekt i programmeringssammanhang.
    har_trivial_konstruktor är_trivialt_standardkonstruerbar
    har_trivial_standardkonstruktor är_trivialt_standardkonstruerbar
    har_trivial_kopia is_trivially_copy_constructible (if retaining the original English term is standard practice)
    har_enkel_flyttkonstruktor är trivialiskt flytt-konstrukterbar
    har_trivial_tilldelning is_trivially_copy_assignable
    har_trivial_flyttilldelning Är_trivially_move_assignable
    har trivial destruktör is_trivialt_destructibel
  • launch::any och launch::sync-policyer

    Icke-standardprinciperna launch::any och launch::sync principerna har tagits bort. Använd i stället för launch::any.launch:async | launch:deferred För launch::syncanvänder du launch::deferred. Se initiera uppräkning.

MFC och ATL

  • Microsoft Foundation-klasser (MFC)

    ingår inte längre i en "typisk" installation av Visual Studio på grund av dess stora storlek. Om du vill installera MFC väljer du alternativet Anpassad installation i Visual Studio 2015-installationen. Om du redan har Visual Studio 2015 installerat kan du installera MFC genom att köra Visual Studio-installationen igen. Välj alternativet Anpassad installation och välj sedan Microsoft Foundation-klasser. Du kan köra Visual Studio-installationen från Kontrollpanelenskontrollprogram och funktioner eller från installationsmediet.

    Visual C++ Redistributable Package innehåller fortfarande det här biblioteket.

Parallellkörning

  • Yield-makro från Windows.h i konflikt med concurrency::context::yield

    Concurrency Runtime använde tidigare #undef för att odefiniera makrot Yield, för att undvika konflikter mellan det Yield-makro som definierats i Windows.h och concurrency::Context::Yield-funktionen. Detta #undef har tagits bort och ett nytt icke-konfliktskapande motsvarande API-anrop concurrency::Context::YieldExecution har lagts till. Om du vill undvika konflikter med Yield kan du antingen uppdatera koden för att anropa YieldExecution funktionen i stället, eller omge Yield funktionsnamnet med parenteser på anropsplatser, som i följande exempel:

    (concurrency::Context::Yield)();
    

Förbättringar av kompilatorns överensstämmelse i Visual Studio 2015

När du uppgraderar kod från tidigare versioner kan du också stöta på kompilatorfel som beror på överensstämmelseförbättringar som gjorts i Visual Studio 2015. Dessa förbättringar bryter inte binär kompatibilitet från tidigare versioner av Visual Studio, men de kan generera kompilatorfel där ingen har genererats tidigare. Mer information finns i Visual C++ Nyheter 2003 till och med 2015.

I Visual Studio 2015 kan pågående förbättringar av kompilatorefterlevnad ibland ändra hur kompilatorn förstår din befintliga källkod. Därför kan du stöta på nya eller olika fel under bygget, eller till och med beteendeskillnader i kod som tidigare skapats och som verkade köras korrekt.

Lyckligtvis har dessa skillnader liten eller ingen inverkan på de flesta av din källkod. När källkoden eller andra ändringar behövs för att åtgärda dessa skillnader tenderar korrigeringarna att vara små och raka. Vi har inkluderat många exempel på tidigare godtagbar källkod som kan behöva ändras (före) och korrigeringarna för att korrigera dem (efter).

Även om dessa skillnader kan påverka källkoden eller andra byggartefakter påverkar de inte binär kompatibilitet mellan uppdateringar av Visual Studio-versioner. En brytande ändring är allvarligare och kan påverka binär kompatibilitet, men den här typen av kompatibilitetsbrott sker bara mellan större versioner av Visual Studio, till exempel mellan Visual Studio 2013 och Visual Studio 2015. För information om de ändringar som skedde mellan Visual Studio 2013 och Visual Studio 2015, se Visual Studio 2015 Conformance Changes.

Anpassningsförbättringar i Visual Studio 2015

  • /Zc:forScope- alternativ

    Kompilatoralternativet /Zc:forScope- är inaktuellt och tas bort i en framtida version.

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

    Vanligtvis användes det här alternativet för att tillåta icke-standardkod som använder loopvariabler efter den punkt där de enligt standarden borde ha gått utanför omfånget. Det var bara nödvändigt när du kompilerade med /Za alternativet eftersom det alltid är tillåtet att använda en for-loopvariabel efter slutet av loopen utan /Za. Om du inte bryr dig om standardefterlevnad (till exempel om koden inte är avsedd att vara portabel för andra kompilatorer) kan du inaktivera /Za alternativet (eller ange egenskapen Inaktivera språktillägg till Nej). Om du bryr dig om att skriva portabel, standardkonform kod bör du skriva om koden så att den överensstämmer med standarden genom att flytta deklarationen av sådana variabler till en punkt utanför loopen.

    // 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 kompilatoralternativ

    Kompilatoralternativet /Zg (Generera funktionsprototyper) är inte längre tillgängligt. Det här kompilatoralternativet var tidigare inaktuellt.

  • Du kan inte längre köra enhetstester med C++/CLI från kommandoraden med mstest.exe. Använd i stället vstest.console.exe. Se VSTest.Console.exe kommandoradsalternativ.

  • nyckelordet 'mutable'

    Lagringsklassspecificeraren mutable tillåts inte längre på platser där den tidigare kompilerades utan fel. Nu ger kompilatorn felet C2071 (ogiltig lagringsklass). Enligt standarden mutable kan specificeraren endast tillämpas på namn på klassdatamedlemmar och kan inte tillämpas på namn som deklarerats som const eller statiska och kan inte tillämpas på referensmedlemmar.

    Tänk till exempel på följande kod:

    struct S
    {
        mutable int &r;
    };
    

    Tidigare versioner av kompilatorn accepterade detta, men nu ger kompilatorn följande fel:

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

    Åtgärda felet genom att ta bort det redundanta mutable nyckelordet.

  • char_16_t och char32_t

    Du kan inte längre använda char16_t eller char32_t som alias i en typedef, eftersom dessa typer nu behandlas som inbyggda. Det var vanligt att användare och biblioteksförfattare definierade char16_t och char32_t som alias uint16_t för respektive uint32_t.

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

    Om du vill uppdatera koden tar du bort deklarationerna typedef och byter namn på andra identifierare som kolliderar med dessa namn.

  • Mallparametrar som inte är av typen

    Viss kod som omfattar mallparametrar som inte är av typen kontrolleras nu korrekt för typkompatibilitet när du anger explicita mallargument. Följande kod kompileras till exempel utan fel i tidigare versioner av Visual Studio.

    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>();
    }
    

    Den nuvarande kompilatorn ger korrekt ett felmeddelande eftersom mallparametertypen inte matchar mallargumentet (parametern är en pekare till en konstant medlem, men funktionen f är inte konstant):

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

    Om du vill åtgärda det här felet i koden kontrollerar du att typen av mallargument som du använder matchar mallparameterns deklarerade typ.

  • __declspec(align)

    Kompilatorn accepterar inte längre __declspec(align) vid funktioner. Den här konstruktionen ignorerades alltid, men nu genererar den ett kompilatorfel.

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

    Åtgärda problemet genom att ta bort __declspec(align) från funktionsdeklarationen. Eftersom det inte hade någon effekt ändras ingenting om du tar bort det.

  • Undantagshantering

    Det finns ett par ändringar i undantagshantering. För det första måste undantagsobjekt vara antingen kopierbara eller flyttbara. Följande kod kompileras i Visual Studio 2013, men kompileras inte i Visual Studio 2015:

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

    Problemet är att kopieringskonstruktorn är privat, så objektet kan inte kopieras på samma sätt som vid normal hantering av ett undantag. Detsamma gäller när kopieringskonstruktorn deklareras explicit.

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

    Om du vill uppdatera koden kontrollerar du att kopieringskonstruktorn för undantagsobjektet är public och inte har markerats explicit.

    Att fånga ett undantag efter värde kräver också att undantagsobjektet kan kopieras. Följande kod kompileras i Visual Studio 2013, men kompileras inte i Visual Studio 2015:

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

    Du kan åtgärda det här problemet genom att ändra parametertypen för catch till en referens.

    catch (D& d)
    {
    }
    
  • Strängliteraler följda av makron

    Kompilatorn stöder nu användardefinierade literaler. Därför tolkas strängliteraler följt av makron utan mellanliggande blanksteg som användardefinierade literaler, vilket kan ge fel eller oväntade resultat. I tidigare kompilatorer kompilerades till exempel följande kod:

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

    Kompilatorn tolkade den här koden som en strängliteral "hello" följt av ett makro, som expanderas till "där", och sedan sammanfogades de två strängliteralerna till en. I Visual Studio 2015 tolkar kompilatorn den här sekvensen som en användardefinierad literal, men eftersom det inte finns någon matchande användardefinierad literal _x definierad ger den ett fel.

    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?
    

    Åtgärda problemet genom att lägga till ett blanksteg mellan strängkonstanten och makrot.

  • Intilliggande strängliteraler

    På samma sätt som i föregående, på grund av relaterade ändringar i strängparsning, tolkades angränsande strängliteraler (antingen breda eller smala teckensträngliteraler) utan blanksteg som en enda sammanfogad sträng i tidigare versioner av Visual C++. I Visual Studio 2015 måste du nu lägga till blanksteg mellan de två strängarna. Följande kod måste till exempel ändras:

    char * str = "abc""def";
    

    För att åtgärda problemet, lägg till ett blanksteg mellan de två strängarna:

    char * str = "abc" "def";
    
  • Placering ny och ta bort

    En ändring har gjorts i operatorn delete för att anpassa den till C++14-standarden. Information om standardändringen finns på C++ Size Deallocation. Ändringarna lägger till en form av den globala delete operatorn som tar en storleksparameter. Den brytande ändringen är att om du tidigare använde en operator delete med samma signatur (för att motsvara en placement new-operator) får du ett kompilatorfel (C2956, som inträffar när den nya placeringen används, eftersom det är där i koden kompilatorn försöker identifiera en lämplig matchande delete-operator).

    Funktionen void operator delete(void *, size_t) var en placement delete-operator som motsvarar placement new-funktionenvoid * operator new(size_t, size_t) i C++11. Med C++14-storleksbaserad avallokering är den här borttagningsfunktionen nu en vanlig frigöringsfunktion (global delete operator). Standarden kräver att om användningen av en ny placering söker upp en motsvarande borttagningsfunktion och hittar en vanlig frigöringsfunktion är programmet felaktigt utformat.

    Anta till exempel att koden definierar både en ny placering och en placeringsborttagning:

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

    Problemet uppstår på grund av matchningen i funktionssignaturer mellan en placement delete-operator som du har definierat och den nya globale sized-operatorn . Fundera på om du kan använda en annan typ än size_t för någon placement new och delete-operatorer. Typen av size_ttypedef är kompilatorberoende. Det är ett typedef för unsigned int i MSVC. En bra lösning är att använda en uppräkningstyp som den här:

    enum class my_type : size_t {};
    

    Ändra sedan definitionen av placering ny och delete använd den här typen som det andra argumentet i stället för size_t. Du måste också uppdatera anropen till "placement new" för att passera den nya typen (till exempel genom att använda static_cast<my_type> för att konvertera från heltalsvärdet) och uppdatera definitionen av new och delete för att återkonvertera till heltalstypen. Du behöver inte använda en enum för detta. En klasstyp med en size_t medlem fungerar också.

    En alternativ lösning är att du kan eliminera placement new helt och hållet. Om koden använder en ny placering för att implementera en minnespool där placeringsargumentet är storleken på objektet som allokeras eller tas bort, kan funktionen för storleksfördelning vara lämplig för att ersätta din egen kod för den anpassade minnespoolen, och du kan bli av med placeringsfunktionerna och bara använda din egen tvåargumentsoperator delete i stället för placeringsfunktionerna.

    Om du inte vill uppdatera koden omedelbart kan du återgå till det gamla beteendet med hjälp av kompilatoralternativet /Zc:sizedDealloc-. Om du använder det här alternativet finns inte borttagningsfunktionerna med två argument och kommer inte att orsaka någon konflikt med din placerings-borttagningsoperator.

  • Unionsdatamedlemmar

    Datamedlemmar i fackföreningar kan inte längre ha referenstyper. Följande kod kompilerades korrekt i Visual Studio 2013, men genererar ett fel i Visual Studio 2015.

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

    Föregående kod genererar följande fel:

    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
    

    Åtgärda problemet genom att ändra referenstyperna till en pekare eller ett värde. Om du ändrar typen till en pekare krävs ändringar i koden som använder union-fältet. Om du ändrar koden till ett värde ändras data som lagras i unionen, vilket påverkar andra fält eftersom fält i unionstyper delar samma minne. Beroende på värdets storlek kan det också ändra storleken på unionen.

  • Anonyma fackföreningar är nu mer överensstämmande med standarden. Tidigare versioner av kompilatorn genererade en explicit konstruktor och destructor för anonyma fackföreningar. Dessa kompilatorgenererade funktioner tas bort i Visual Studio 2015.

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

    Föregående kod genererar följande fel i 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
    

    Lös problemet genom att ange egna definitioner av konstruktorn och/eller destruktor.

    struct S
    {
        // Provide a default constructor by adding an empty function body.
        S() {}
    };
    
    union
    {
        struct
        {
            S s;
        };
    } u;
    
  • Fackföreningar med anonyma structs

    För att uppfylla standarden har körningsbeteendet ändrats för medlemmar i anonyma strukturer i fackföreningar. Konstruktorn för anonyma strukturmedlemmar i en union anropas inte längre implicit när en sådan union skapas. Dessutom kallas inte längre destruktorn för anonyma strukturmedlemmar i en union implicit när unionen går utanför sitt omfång. Tänk på följande kod, där en union U innehåller en anonym struktur med en namngiven medlemsstruktur S, som har en destruktor.

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

    I Visual Studio 2013 anropas konstruktorn för S när unionen skapas och destruktören för S anropas när stacken för funktionen f rensas. Men i Visual Studio 2015 anropas inte konstruktorn och destruktören. Kompilatorn varnar om den här beteendeändringen.

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

    Om du vill återställa det ursprungliga beteendet ger du den anonyma strukturen ett namn. Körningsbeteendet för icke-anonyma strukturer är detsamma, oavsett kompilatorversion.

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

    Alternativt kan du prova att flytta koden för konstruktorn och destruktorn till nya funktioner och lägga till anrop till dessa funktioner från konstruktorn och destruktorn för unionen.

    #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;
    }
    
  • Mallupplösning

    Ändringar har gjorts i namnupplösning för mallar. I C++, när du överväger kandidater för lösning av ett namn, kan det vara så att ett eller flera namn som övervägs som potentiella matchningar skapar en ogiltig mallinstansiering. Dessa ogiltiga instanser orsakar normalt inte kompilatorfel, en princip som kallas SFINAE (substitutionsfel är inte ett fel).

    Om SFINAE kräver att kompilatorn instansierar specialiseringen av en klassmall är nu eventuella fel som inträffar under den här processen kompilatorfel. I tidigare versioner skulle kompilatorn ignorera sådana fel. Tänk till exempel på följande kod:

    #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);
    }
    

    Om du kompilerar med den aktuella kompilatorn får du följande fel:

    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
    ]
    

    Detta beror på att klassen D inte har definierats ännu vid tidpunkten för det första anropet av is_base_of.

    I det här fallet är korrigeringen att inte använda sådana typegenskaper förrän klassen har definierats. Om du flyttar definitionerna för B och D till början av kodfilen löses felet. Om definitionerna finns i huvudfiler kontrollerar du ordningen på include-instruktionerna för huvudfilerna för att se till att alla klassdefinitioner kompileras innan de problematiska mallarna används.

  • Kopia-konstruktorer

    I både Visual Studio 2013 och Visual Studio 2015 genererar kompilatorn en kopieringskonstruktor för en klass om klassen har en användardefinierad flyttkonstruktor men ingen användardefinierad kopieringskonstruktor. I Dev14 är den här implicit genererade kopieringskonstruktorn också märkt "= delete".

  • main som deklarerats som extern "C" kräver nu en returtyp.

    Följande kod genererar nu C4430.

    extern "C" __cdecl main(){} // C4430
    

    Åtgärda felet genom att lägga till returtypen:

    extern "C" int __cdecl main(){} // OK
    
  • typename är inte tillåtet i en medlemsinitialiserare

    Följande kod genererar nu C2059:

    template<typename T>
    struct S1 : public T::type
    {
        S1() : typename T::type() // C2059
        {
        }
    };
    
    struct S2 {
        typedef S2 type;
    };
    
    S1<S2> s;
    

    Åtgärda felet genom att ta bort typename från initieraren:

    S1() : T::type() // OK
    ...
    
  • Lagringsklassen för explicita specialiseringar ignoreras.

    I följande kod ignoreras den statiska lagringsklassspecificeraren

    template <typename T>
    void myfunc(T h)
    {
    }
    
    template<>
    static void myfunc(double h) // static is ignored
    {
    }
    
  • En konstant som används i en static_assert i en klassmall misslyckas alltid.

    Följande kod gör att det static_assert alltid misslyckas:

    template <size_t some_value>
    struct S1
    {
        static_assert(false, "default not valid"); // always invoked
    
    };
    
    //other partial specializations here
    

    Du kan kringgå det här problemet genom att omsluta värdet i en struct:

    template <size_t some_value>
    struct constant_false {
        static const bool value = false;
    };
    
    template <size_t some_value>
    struct S1
    {
        static_assert(constant_false<some_value>::value, "default not valid");
    };
    
    //other partial specializations here
    
  • Regler som tillämpas för framåtriktade deklarationer. (Gäller endast för C.)

    Följande kod genererar nu C2065:

    struct token_s;
    typedef int BOOL;
    typedef int INT;
    
    typedef int(*PFNTERM)(PTOKEN, BOOL, INT); // C2065: 'PTOKEN' : undeclared identifier
    

    Åtgärda problemet genom att lägga till rätt framåtdeklarationer:

    struct token_s;
    typedef int BOOL;
    typedef int INT;
    
    // forward declarations:
    typedef struct token_s TOKEN;
    typedef TOKEN *PTOKEN;
    
    typedef int(*PFNTERM)(PTOKEN, BOOL, INT);
    
  • Mer konsekvent tillämpning av funktionspekartyper

    Följande kod genererar nu C2197:

    typedef int(*F1)(int);
    typedef int(*F2)(int, int);
    
    void func(F1 f, int v1, int v2)
    {
        f(v1, v2); // C2197
    }
    
  • Tvetydiga anrop till överbelastade funktioner

    Följande kod genererar nu C266: "N::bind": tvetydigt anrop till överbelastad funktion

    template<typename R, typename T, typename T1, typename A1>
    void bind(R(T::*)(T1), A1&&);
    
    namespace N
    {
        template <typename T, typename R, typename ... Tx>
        void bind(R(T::*)(Tx...), T* ptr);
    }
    
    using namespace N;
    
    class Manager
    {
    public:
        void func(bool initializing);
    
        void mf()
        {
            bind(&Manager::func, this); //C2668
        }
    };
    

    För att åtgärda felet kan du helt kvalificera anropet till bind: N::bind(...). Men om den här ändringen visas via en odeklarerad identifierare (C2065) kan det vara lämpligt att åtgärda detta med en using deklaration i stället.

    Det här mönstret sker ofta med ComPtr och andra typer i Microsoft::WRL namnområdet.

  • Åtgärda felaktig adress för

    Följande kod genererar nu C2440: '=': kan inte konvertera från "typ *" till "typ". Åtgärda felet genom att ändra &(typ) till (typ) och (&f()) till (f()).

    // C
    typedef void (*type)(void);
    
    void f(int i, type p);
    void g(int);
    void h(void)
    {
        f(0, &(type)g);
    }
    
    // C++
    typedef void(*type)(void);
    
    type f();
    
    void g(type);
    
    void h()
    {
        g(&f());
    }
    
  • Strängliteral är en konstant matris

    Följande kod genererar nu C2664: "void f(void )": kan inte konvertera argument 1 från "const char ()[2]" till "void *"

    void f(void *);
    
    void h(void)
    {
        f(&__FUNCTION__);
        void *p = &"";
    }
    

    Åtgärda felet genom att ändra funktionsparametertypen till const void*, eller ändra brödtexten h för så att den ser ut som i det här exemplet:

    void h(void)
    {
        char name[] = __FUNCTION__;
        f( name);
        void *p = &"";
    }
    
  • C++11 UDL-strängar

    Följande kod genererar nu felet C3688: det ogiltiga literalsuffixet "L"; literaloperatorn eller literaloperatormallen "operatorn ""L" hittades inte

    #define MACRO
    
    #define STRCAT(x, y) x\#\#y
    
    int main(){
    
        auto *val1 = L"string"MACRO;
        auto *val2 = L"hello "L"world";
    
        std::cout << STRCAT(L"hi ", L"there");
    }
    

    Åtgärda felet genom att ändra koden för att lägga till ett blanksteg:

    #define MACRO
    
    // Remove ##. Strings are automatically
    // concatenated so they aren't needed
    #define STRCAT(x, y) x y
    
    int main(){
        //Add space after closing quote
        auto *val1 = L"string" MACRO;
        auto *val2 = L"hello " L"world";
    
        std::cout << STRCAT(L"hi ", L"there");
    }
    

    I exemplet ovan MACRO parsas inte längre som två token (en sträng följt av ett makro). Nu parsas den som en enda token-UDL. Samma sak gäller för L""L", som tidigare parsades som L"" och L", och som nu parsas som L""L och "".

    Reglerna för strängsammanfogning har också bragts i överensstämmelse med standarden, vilket innebär att L"a" "b" är ekvivalent med L"ab". Tidigare utgåvor av Visual Studio accepterade inte sammanfogning av strängar med olika teckenbredd.

  • C++11 tomt tecken har tagits bort

    Följande kod genererar nu felet C2137: tom teckenkonstant

    bool check(wchar_t c){
        return c == L''; //implicit null character
    }
    

    Åtgärda felet genom att ändra koden så att null-värdet blir explicit:

    bool check(wchar_t c){
        return c == L'\0';
    }
    
  • MFC-undantag kan inte fångas upp av värde eftersom de inte kan kopieras

    Följande kod i ett MFC-program orsakar nu felet C2316: "D": kan inte fångas eftersom destruktorn och/eller kopieringskonstruktorn är otillgänglig eller borttagen

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

    För att åtgärda koden kan du ändra catch-blocket till catch (const D &) , men den bättre lösningen är vanligtvis att använda MFC TRY/CATCH-makron.

  • alignof är nu ett nyckelord

    Följande kod genererar nu felet C2332: "class": saknade taggnamn. Om du vill åtgärda koden måste du byta namn på klassen eller, om klassen utför samma arbete som alignof, bara ersätta klassen med det nya nyckelordet.

    class alignof{}
    
  • constexpr är nu ett nyckelord

    Följande kod genererar nu felet C2059: syntaxfel: ')'. Om du vill åtgärda koden måste du byta namn på alla funktions- eller variabelnamn som kallas constexpr.

    int constexpr() {return 1;}
    
  • Flyttbara typer kan inte vara beständiga

    När en funktion returnerar en typ som är avsedd att flyttas ska dess returtyp inte vara const.

  • Borttagna kopieringskonstruktorer

    Följande kod genererar nu C2280 'S::S(S &&)': försöker referera till en borttagen funktion:

    struct S{
        S(int, int);
        S(const S&) = delete;
        S(S&&) = delete;
    };
    
    S s2 = S(2, 3); //C2280
    

    Åtgärda felet genom att använda direktinitiering för S2:

    struct S{
        S(int, int);
        S(const S&) = delete;
        S(S&&) = delete;
    };
    
    S s2 = {2,3}; //OK
    
  • Konvertering till funktionspekare sker endast när ingen lambda-capture finns

    Följande kod genererar C2664 i Visual Studio 2015.

    void func(int(*)(int)) {}
    
    int main() {
    
        func([=](int val) { return val; });
    }
    

    Åtgärda felet genom att ta bort = från avbildningslistan.

  • Tvetydiga anrop som involverar konverteringsoperatorer

    Följande kod genererar nu felet C2440: "type cast": kan inte konvertera från "S2" till "S1":

    struct S1 {
        S1(int);
    };
    
    struct S2 {
        operator S1();
        operator int();
    };
    
    void f(S2 s2)
    {
        (S1)s2;
    }
    

    Om du vill åtgärda felet anropar du uttryckligen konverteringsoperatorn:

    void f(S2 s2)
    {
        //Explicitly call the conversion operator
        s2.operator S1();
        // Or
        S1((int)s2);
    }
    

    Följande kod genererar nu felet C2593: operatorn =är tvetydig:

    struct S1 {};
    
    struct S2 {
        operator S1&();
        operator S1() const;
    };
    
    void f(S1 *p, S2 s)
    {
        *p = s;
    }
    

    Om du vill åtgärda felet anropar du uttryckligen konverteringsoperatorn:

    void f(S1 *p, S2 s)
    {
        *p = s.operator S1&();
    }
    
  • Åtgärda ogiltig kopieringsinitiering i initiering av icke-statiska datamedlemmar (NSDMI)

    Följande kod genererar nu felet C2664: S1::S1(S1 &&): kan inte konvertera argument 1 från "bool" till "const S1 &":

    struct S1 {
        explicit S1(bool);
    };
    
    struct S2 {
        S1 s2 = true; // error
    };
    

    Åtgärda felet genom att använda direktinitiering:

    struct S2 {
    S1 s1{true}; // OK
    };
    
  • Komma åt konstruktorer i decltype-instruktioner

    Följande kod genererar nu C2248: "S::S": kan inte komma åt den privata medlem som deklareras i klassen "S":

    class S {
        S();
    public:
        int i;
    };
    
    class S2 {
        auto f() -> decltype(S().i);
    };
    

    Åtgärda felet genom att lägga till en vändeklaration för S2 i S:

    class S {
        S();
        friend class S2; // Make S2 a friend
    public:
        int i;
    };
    
  • Standard-ctor för lambda tas implicit bort

    Följande kod genererar nu felet C3497: du kan inte skapa en instans av en lambda:

    void func(){
        auto lambda = [](){};
    
        decltype(lambda) other;
    }
    

    Åtgärda felet genom att ta bort behovet av att anropa standardkonstruktorn. Om lambda inte fångar något kan det kastas till en funktionspekare.

  • Lambdas med en borttagen tilldelningsoperator

    Följande kod genererar nu felet C2280:

    #include <memory>
    #include <type_traits>
    
    template <typename T, typename D>
    std::unique_ptr<T, typename std::remove_reference<D &&>::type> wrap_unique(T *p, D &&d);
    
    void f(int i)
    {
        auto encodedMsg = wrap_unique<unsigned char>(nullptr, [i](unsigned char *p) {
        });
        encodedMsg = std::move(encodedMsg);
    }
    

    Åtgärda felet genom att ersätta lambda med en functor-klass eller ta bort behovet av att använda tilldelningsoperatorn.

  • Försöker flytta ett objekt med borttagen kopieringskonstruktor

    Följande kod genererar nu felet C2280: "moveable::moveable(const moveable &)": försöker referera till en borttagen funktion

    struct moveable {
    
        moveable() = default;
        moveable(moveable&&) = default;
        moveable(const moveable&) = delete;
    };
    
    struct S {
        S(moveable && m) :
            m_m(m)//copy constructor deleted
        {}
        moveable m_m;
    };
    

    Åtgärda felet genom att använda std::move i stället:

    S(moveable && m) :
        m_m(std::move(m))
    
  • Lokal klass kan inte referera till andra lokala klasser som definierats senare i samma funktion

    Följande kod genererar nu felet C2079: "s" använder odefinierad struct "main::S2"

    int main()
    {
        struct S2;
        struct S1 {
            void f() {
                S2 s;
            }
        };
        struct S2 {};
    }
    

    Åtgärda felet genom att flytta upp definitionen av S2:

    int main()
    {
        struct S2 { //moved up
        };
    
    struct S1 {
        void f() {
            S2 s;
            }
        };
    }
    
  • Det går inte att anropa en skyddad baskonstruktor i en härledd konstruktors kropp.

    Följande kod genererar nu felet C2248: "S1::S1": kan inte komma åt skyddad medlem som deklarerats i klassen "S1"

    struct S1 {
    protected:
        S1();
    };
    
    struct S2 : public S1 {
        S2() {
            S1();
        }
    };
    

    Åtgärda felet genom att ta S2 bort anropet till S1() från konstruktorn och vid behov placera det i en annan funktion.

  • {} förhindrar konvertering till pekare

    Följande kod genererar nu C2439 'S::p': medlemmen kunde inte initieras

    struct S {
        S() : p({ 0 }) {}
        void *p;
    };
    

    Åtgärda felet genom att ta bort klammerparenteserna från runt 0 eller annars använda nullptr i stället, som du ser i det här exemplet:

    struct S {
        S() : p(nullptr) {}
        void *p;
    };
    
  • Felaktig makrodefinition och användning med parenteser

    Följande exempel genererar nu felet C2008: ';': oväntat i makrodefinitionen

    #define A; //cause of error
    
    struct S {
        A(); // error
    };
    

    Åtgärda problemet genom att ändra den översta raden till #define A();

    Följande kod genererar felet C2059: syntaxfel: ')'

    //notice the space after 'A'
    #define A () ;
    
    struct S {
        A();
    };
    

    Åtgärda koden genom att ta bort utrymmet mellan A och ().

    Följande kod genererar felet C2091: funktionen returnerar funktionen:

    #define DECLARE void f()
    
    struct S {
        DECLARE();
    };
    

    Åtgärda felet genom att ta bort parenteserna efter DECLARE i S: DECLARE;.

    Följande kod genererar felet C2062: skriv "int" oväntat

    #define A (int)
    
    struct S {
        A a;
    };
    

    Du kan åtgärda problemet genom att definiera A så här:

    #define A int
    
  • Extra parens i deklarationer

    Följande kod genererar felet C2062: skriv "int" oväntat

    struct S {
        int i;
        (int)j;
    };
    

    Åtgärda felet genom att ta bort parenteserna runt j. Om parenteserna behövs för tydlighetens skull använder du en typedef.

  • Kompilatorgenererade konstruktorer och __declspec(novtable)

    I Visual Studio 2015 finns det en ökad sannolikhet att kompilatorgenererade infogade konstruktorer av abstrakta klasser med virtuella basklasser kan exponera felaktig användning av __declspec(novtable) när de används i kombination med __declspec(dllimport).

  • auto kräver ett enda uttryck i direct-list-initialization

    Följande kod genererar nu felet C3518: "testPositions": i en kontext för direkt listinitiering kan typen för "auto" bara härledas från ett enda initialiseraruttryck

    auto testPositions{
        std::tuple<int, int>{13, 33},
        std::tuple<int, int>{-23, -48},
        std::tuple<int, int>{38, -12},
        std::tuple<int, int>{-21, 17}
    };
    

    För att åtgärda felet är en möjlighet att initiera testPositions på följande sätt:

    std::tuple<int, int> testPositions[]{
        std::tuple<int, int>{13, 33},
        std::tuple<int, int>{-23, -48},
        std::tuple<int, int>{38, -12},
        std::tuple<int, int>{-21, 17}
    };
    
  • Att kontrollera typer versus pekare till typer för is_convertible

    Följande kod gör nu att den statiska försäkran misslyckas.

    struct B1 {
    private:
        B1(const B1 &);
    };
    struct B2 : public B1 {};
    struct D : public B2 {};
    
    static_assert(std::is_convertible<D, B2>::value, "fail");
    

    Åtgärda felet genom att ändra static_assert så att pekarna jämförs med D och B2:

    static_assert(std::is_convertible<D*, B2*>::value, "fail");
    
  • __declspec(novtable) deklarationer måste vara konsekventa

    __declspec deklarationer måste vara konsekventa i alla bibliotek. Följande kod skapar en ODR-överträdelse (one-definition rule):

    //a.cpp
    class __declspec(dllexport)
        A {
    public:
        A();
        A(const A&);
        virtual ~A();
    private:
        int i;
    };
    
    A::A() {}
    A::~A() {}
    A::A(const A&) {}
    
    //b.cpp
    // compile with cl.exe /nologo /LD /EHsc /Osx b.cpp
    #pragma comment(lib, "A")
    class __declspec(dllimport) A
    {
    public: A();
            A(const A&);
            virtual ~A();
    private:
        int i;
    };
    
    struct __declspec(novtable) __declspec(dllexport) B
        : virtual public A {
        virtual void f() = 0;
    };
    
    //c.cpp
    #pragma comment(lib, "A")
    #pragma comment(lib, "B")
    class __declspec(dllimport) A
    {
    public:
        A();
        A(const A&);
        virtual ~A();
    private:
        int i;
    };
    struct  /* __declspec(novtable) */ __declspec(dllimport) B // Error. B needs to be novtable here also.
        : virtual public A
    {
        virtual void f() = 0;
    };
    
    struct C : virtual B
    {
        virtual void f();
    };
    
    void C::f() {}
    C c;
    

Överensstämmelseförbättringar i uppdatering 1

  • Privata virtuella basklasser och indirekt arv

    Tidigare versioner av kompilatorn tillät en härledd klass att anropa medlemsfunktioner i dess indirekt härledda private virtual basklasser. Det här gamla beteendet var felaktigt och överensstämmer inte med C++-standarden. Kompilatorn accepterar inte längre kod som skrivits på det här sättet och utfärdar kompilatorfel C2280 som ett resultat.

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

    Exempel (före)

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

    Exempel (efter)

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

    -eller-

    class base;  // as above
    
    class middle : private virtual base {};
    class top : public virtual middle, private virtual bottom {};
    
    void destroy(top *p)
    {
        delete p;
    }
    
  • Överlagrade operatorn new och operator delete

    Tidigare versioner av kompilatorn tillät att icke-medlemsoperatorn new och icke-medlemsoperatorn delete kunde deklareras som statiska och i andra namnområden än det globala namnområdet. Det här gamla beteendet skapade en risk för att programmet inte skulle anropa den operatorimplementering new eller delete som programmeraren avsåg, vilket resulterade i tysta problem under körning. Kompilatorn accepterar inte längre kod som skrivits på det här sättet och utfärdar kompilatorfel C2323 i stället.

    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.
    

    Exempel (före)

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

    Exempel (efter)

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

    Även om kompilatorn inte ger någon specifik diagnostik anses den infogade operatorn new dessutom vara dåligt utformad.

  • Anropa " operatortyp()" (användardefinierad konvertering) för icke-klasstyper

    Tidigare versioner av kompilatorn tillät att " operatortyp()" anropas på icke-klasstyper samtidigt som den ignoreras tyst. Det gamla beteendet skapade en risk för tyst felaktig kodgenerering, vilket resulterade i oförutsägbart exekveringsbeteende. Kompilatorn accepterar inte längre kod som skrivits på det här sättet och utfärdar kompilatorfel C2228 i stället.

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

    Exempel (före)

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

    Exempel (efter)

    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'
    }
    
  • Redundant typename i utarbetade typspecificerare

    Tidigare versioner av kompilatorn tillät typename i en utarbetad typspecifikation, men koden som skrevs på detta sätt är semantiskt felaktig. Kompilatorn accepterar inte längre kod som skrivits på det här sättet och utfärdar kompilatorfel C3406 i stället.

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

    Exempel (före)

    template <typename class T>
    class container;
    

    Exempel (efter)

    template <class T>  // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case
    class container;
    
  • Skriv avdrag för matriser från en initialiserarlista

    Tidigare versioner av kompilatorn hade inte stöd för typavdrag av matriser från en initialiserarlista. Kompilatorn stöder nu den här typen av typavdrag och därför kan anrop till funktionsmallar som använder initieringslistor nu vara tvetydiga eller så kan en annan överbelastning väljas än i tidigare versioner av kompilatorn. För att lösa dessa problem måste programmet nu uttryckligen ange den överlagring som programmeraren avsåg.

    När det här nya beteendet gör att överbelastningslösningen överväger ytterligare en kandidat som är lika bra som den historiska kandidaten blir anropet tvetydigt och kompilatorn utfärdar kompilatorfelet C2668 som ett resultat.

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

    Exempel 1: Tvetydigt anrop till överbelastad funktion (före)

    // 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
    }
    

    Exempel 1: tvetydigt anrop till överbelastad funktion (efter)

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

    När det här nya beteendet gör att överbelastningslösningen överväger ytterligare en kandidat som är en bättre matchning än den historiska kandidaten, löses samtalet entydigt mot den nya kandidaten, vilket orsakar en förändring i programmets beteende som förmodligen skiljer sig från programmerarens avsedda.

    Exempel 2: ändring i överlagringsupplösning (före)

    // 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 });
    }
    

    Exempel 2: ändring i överbelastningslösning (efter)

    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 });
    }
    
  • Återställning av switch-instruktionsvarningar

    En tidigare version av kompilatorn tog bort några varningar relaterade till switch -instruktioner. Dessa varningar har nu återställts. Kompilatorn utfärdar nu de återställde varningarna och varningar relaterade till specifika fall (inklusive standardfallet) utfärdas nu på raden som innehåller det felaktiga ärendet, i stället för på den sista raden i switch-instruktionen. Som ett resultat av att dessa varningar nu utfärdas på andra rader än tidigare kan varningar som tidigare undertryckts med hjälp av #pragma warning(disable:####) inte längre undertryckas som man tänkt sig. Det kan vara nödvändigt att flytta #pragma warning(disable:####)-direktivet till en rad ovanför det första felaktiga fallet för att undanröja dessa varningar så som avsett. Följande är de återställde varningarna:

    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
    

    Exempel på C4063 (före)

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

    Exempel på C4063 (efter)

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

    Exempel på andra återställde varningar finns i dokumentationen.

  • #include: användning av överordnad katalogspecificerare '..' i sökväg (påverkar /Wall/WXendast )

    Tidigare versioner av kompilatorn identifierade inte användningen av den överordnade katalogspecificeraren .. i direktivens #include sökväg. Kod som skrivs på det här sättet är vanligtvis avsedd att innehålla rubriker som finns utanför projektet genom att felaktigt använda projektrelativa sökvägar. Det här gamla beteendet skapade en risk för att programmet kunde kompileras genom att inkludera en annan källfil än programmeraren avsåg, eller att dessa relativa sökvägar inte skulle vara portabla för andra byggmiljöer. Kompilatorn identifierar och meddelar nu programmeraren av kod som skrivits på det här sättet och utfärdar en valfri kompilatorvarning C4464, om den är aktiverad.

    warning C4464: relative include path contains '..'
    

    Exempel (före)

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

    Exempel (efter)

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

    Även om kompilatorn inte ger någon specifik diagnostik rekommenderar vi också att den överordnade katalogspecificeraren ".." inte ska användas för att ange projektets inkluderingskataloger.

  • #pragma optimize() sträcker sig bortom slutet av huvudfilen (påverkar endast /Wall/WX)

    Tidigare versioner av kompilatorn identifierade inte ändringar i optimeringsflaggans inställningar som undflyr en rubrikfil som ingår i en översättningsenhet. Kompilatorn identifierar och meddelar nu programmeraren av kod som skrivits på det här sättet och utfärdar en valfri kompilatorvarning C4426 på platsen för den felaktiga #include, om den är aktiverad. Den här varningen utfärdas endast om ändringarna står i konflikt med de optimeringsflaggor som angetts av kommandoradsargument till kompilatorn.

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

    Exempel (före)

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

    Exempel (efter)

    // 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"
    
  • Felmatchad #pragma warning(push) och #pragma warning(pop) (påverkar endast /Wall/WX)

    Tidigare versioner av kompilatorn identifierade #pragma warning(push) inte tillståndsändringar som paras ihop med #pragma warning(pop) tillståndsändringar i en annan källfil, vilket sällan är avsett. Det här gamla beteendet skapade en risk för att programmet skulle kompileras med en annan uppsättning varningar aktiverade än programmeraren avsåg, vilket kan leda till tyst felaktigt körningsbeteende. Kompilatorn identifierar och meddelar nu programmeraren av kod som skrivits på det här sättet och utfärdar en valfri kompilatorvarning C5031 på platsen för matchande #pragma warning(pop), om den är aktiverad. Den här varningen innehåller en anteckning som refererar till platsen för motsvarande #pragma varning(push).

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

    Exempel (före)

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

    Exempel (efter)

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

    Även om det är ovanligt är kod skriven på det här sättet ibland avsiktlig. Kod som skrivs på det här sättet är känslig för ändringar i #include ordning. När det är möjligt rekommenderar vi att källkodsfiler hanterar varningstillståndet på ett självständigt sätt.

  • Omatchad #pragma varning(push) (påverkar endast /Wall/WX)

    Tidigare versioner av kompilatorn identifierade inte omatchade tillståndsändringar #pragma warning(push) i slutet av en översättningsenhet. Kompilatorn identifierar nu och meddelar programmeraren om kod skriven på det här sättet och utfärdar en valfri kompilatorvarning C5032 vid platsen för den omatchade #pragma warning(push), om den är aktiverad. Den här varningen utfärdas endast om det inte finns några kompileringsfel i översättningsenheten.

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

    Exempel (före)

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

    Exempel (efter)

    // 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)
    
  • Ytterligare varningar kan utfärdas till följd av förbättrad spårning av #pragma varningstillstånd

    Tidigare versioner av kompilatorn spårade inte tillräckligt noggrant när #pragma varningsläge ändrades för att utfärda alla avsedda varningar. Det här beteendet skapade en risk för att vissa varningar effektivt skulle undertryckas under andra omständigheter än programmeraren avsåg. Kompilatorn spårar nu #pragma warning-tillståndet mer robust, särskilt i relation till tillståndsändringar på #pragma warning inom mallar, och utfärdar vid behov de nya varningarna C5031 och C5032, som är avsedda att hjälpa programmeraren att identifiera oavsiktliga användningar av #pragma warning(push) och #pragma warning(pop).

    Som ett resultat av förbättrad #pragma warning spårning av tillståndsändringar kan varningar som tidigare felaktigt undertryckts eller varningar relaterade till problem som tidigare var feldiagnostiserade nu utfärdas.

  • Förbättrad identifiering av oåtkomlig kod

    Ändringar i C++-standardbiblioteket och förbättrad möjlighet att anropa infogade funktioner jämfört med tidigare versioner av kompilatorn kan göra det möjligt för kompilatorn att bevisa att viss kod nu inte kan nås. Det här nya beteendet kan resultera i nya och vanligare utfärdade instanser av varning C4720.

    warning C4720: unreachable code
    

    I många fall kan den här varningen endast utfärdas när kompilering med optimeringar är aktiverade, eftersom optimeringar kan infoga fler funktionsanrop, eliminera redundant kod eller på annat sätt göra det möjligt att fastställa att viss kod inte kan nås. Vi har observerat att nya instanser av varning C4720 ofta har inträffat i try/catch-block, särskilt när det gäller användning av std::find.

    Exempel (före)

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

    Exempel (efter)

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

Överensstämmelseförbättringar i uppdatering 2

  • Ytterligare varningar och fel kan utfärdas till följd av partiellt stöd för uttrycket SFINAE

    Tidigare versioner av kompilatorn parsade inte vissa typer av uttryck i decltype specificerare på grund av bristande stöd för uttrycket SFINAE. Det här gamla beteendet var felaktigt och överensstämmer inte med C++-standarden. Kompilatorn parsar nu dessa uttryck och har delvis stöd för uttrycket SFINAE på grund av pågående anpassningsförbättringar. Därför utfärdar kompilatorn nu varningar och fel som hittades i uttryck som tidigare versioner av kompilatorn inte parsade.

    När det här nya beteendet parsar ett decltype uttryck som innehåller en typ som inte har deklarerats ännu, utfärdar kompilatorn kompilatorfelet C2039 som ett resultat.

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

    Exempel 1: Användning av en odeklarerad typ (före)

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

    Exempel 1 (efter)

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

    När det här nya beteendet parsar ett decltype uttryck som saknar nödvändig användning av nyckelordet typename för att ange att ett beroende namn är en typ, utfärdar kompilatorn kompilatorn varning C4346 tillsammans med kompilatorfel 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'
    

    Exempel 2: Beroende namn är inte en typ (före)

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

    Exempel 2 (efter)

    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 medlemsvariabler förhindrar implicit definierade konstruktorer och tilldelningsoperatorer

    Tidigare versioner av kompilatorn tillät en klass som har volatile medlemsvariabler att ha standardkonstruktorer för kopiering/flytt och standardoperatorer för kopierings-/flytttilldelning automatiskt genererade. Det här gamla beteendet var felaktigt och överensstämmer inte med C++-standarden. Kompilatorn anser nu att en klass som har volatile medlemsvariabler har icke-triviala bygg- och tilldelningsoperatorer, vilket förhindrar att standardimplementeringar av dessa operatorer genereras automatiskt. När en sådan klass är medlem i en union (eller en anonym union i en klass) definieras kopierings-/flyttkonstruktorerna och kopierings-/flytttilldelningsoperatorerna för facket (eller klassen som innehåller den anonyma unionen) implicit som borttagna. Att försöka konstruera eller kopiera unionen (eller klassen som innehåller den anonyma unionen) utan att uttryckligen definiera dem är ett fel och kompilatorn utfärdar kompilatorfelet C2280 som ett resultat.

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

    Exempel (före)

    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
    

    Exempel (efter)

    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
    
  • Statiska medlemsfunktioner stöder inte cv-kvalificeringar.

    Tidigare versioner av Visual Studio 2015 tillät statiska medlemsfunktioner kunna ha cv-kvalificerare. Det här beteendet beror på en regression i Visual Studio 2015 och Visual Studio 2015 Update 1. Visual Studio 2013 och tidigare versioner av kompilatorn avvisar kod som skrivits på det här sättet. Beteendet för Visual Studio 2015 och Visual Studio 2015 Update 1 är felaktigt och överensstämmer inte med C++-standarden. Visual Studio 2015 Update 2 avvisar kod som skrivits på det här sättet och utfärdar kompilatorfel C2511 i stället.

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

    Exempel (före)

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

    Exempel(efter)

    struct A
    {
        static void func();
    };
    
    void A::func() {}  // removed const
    
  • Framåtdeklaration av enum-typ tillåts inte i WinRT-kod (påverkar endast /ZW)

    Kod som kompilerats för Windows Runtime (WinRT) tillåter inte att typer framdeklareras, på samma sätt som när hanterad C++-kod kompileras för .Net Framework med hjälp av kompilatorswitchen enum. Det här beteendet säkerställer att storleken på en uppräkning alltid är känd och kan projiceras korrekt till WinRT-typsystemet. Kompilatorn avvisar kod som skrivits på det här sättet och utfärdar kompilatorfel C2599 tillsammans med kompilatorfel C3197.

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

    Exempel (före)

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

    Exempel (efter)

              // forward declaration of CustomEnum removed
    namespace A {
        public enum class CustomEnum : int32
        {
            Value1
        };
    }
    
    public ref class Component sealed
    {
    public:
        CustomEnum f()
        {
            return CustomEnum::Value1;
        }
    };
    
  • Överlagrad icke-medlemsoperator ny och operatörsborttagning kanske inte deklareras infogad (nivå 1 (/W1) on-by-default)

    Tidigare versioner av kompilatorn utfärdar ingen varning när icke-medlemsoperatorns nya och operatörsborttagningsfunktioner deklareras infogade. Kod som skrivs på det här sättet är dåligt utformad (ingen diagnostik krävs) och kan orsaka minnesproblem till följd av felmatchning av new- och delete-operatorer (särskilt när de används tillsammans med deallokering baserad på storlek) som kan vara svår att upptäcka. Kompilatorn utfärdar nu kompilatorvarning C4595 för att identifiera kod som skrivits på det här sättet.

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

    Exempel (före)

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

    Exempel (efter)

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

    Att åtgärda kod som skrivs på det här sättet kan kräva att operatordefinitionerna flyttas från en rubrikfil och till en motsvarande källfil.

Överensstämmelseförbättringar i uppdatering 3

  • std::is_convertable identifierar nu självtilldelning (standardbibliotek)

    Tidigare versioner av typdraget std::is_convertable identifierade inte korrekt självtilldelning av en klasstyp när dess kopieringskonstruktor tas bort eller är privat. Nu ställs std::is_convertable<>::value korrekt in på false när den tillämpas på en klasstyp med en borttagen eller privat kopieringskonstruktor.

    Det finns ingen kompilatordiagnostik associerad med den här ändringen.

    Exempel

    #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");
    

    I tidigare versioner av kompilatorn passerar de statiska påståendena längst ned i det här exemplet eftersom std::is_convertable<>::value felaktigt ställdes in som true. std::is_convertable<>::value är nu korrekt inställd på false, vilket gör att de statiska påståendena misslyckas.

  • Standard- eller borttagna triviala kopierings- och flyttkonstruktorer respekterar åtkomstspecifierare

    Tidigare versioner av kompilatorn kontrollerade inte åtkomstspecificeraren för standardmässiga eller borttagna triviala kopierings- och flyttkonstruktorer innan de kunde anropas. Det här gamla beteendet var felaktigt och överensstämmer inte med C++-standarden. I vissa fall skapade det här gamla beteendet en risk för tyst felaktig kodgenerering, vilket resulterade i oförutsägbart körningsbeteende. Kompilatorn kontrollerar nu åtkomstspecificeraren för standardmässiga eller borttagna triviala kopierings- och flyttkonstruktorer för att avgöra om den kan anropas, och om inte, utfärdar kompilatorn varning C2248 som ett resultat.

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

    Exempel (före)

    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
    }
    

    Exempel (efter)

    class S {
    public:
        S() = default;
    private:
        S(const S&) = default;
    };
    
    void f(const S&);  // pass S by reference
    
    int main()
    {
        S s;
        f(s);
    }
    
  • Utfasning av tilldelat ATL-kodstöd (nivå 1 (/W1) on-by-default)

    Tidigare versioner av kompilatorn stödde tillskriven ATL-kod. Som nästa fas för att ta bort stöd för tillskriven ATL-kod som började i Visual Studio 2008 har den tillskrivna ATL-koden blivit inaktuell. Kompilatorn utfärdar nu kompilatorvarning C4467 för att identifiera den här typen av inaktuell kod.

    warning C4467: Usage of ATL attributes is deprecated
    

    Om du vill fortsätta använda tilldelad ATL-kod tills supporten har tagits bort från kompilatorn kan du inaktivera den här varningen genom att skicka argumenten /Wv:18 eller /wd:4467 kommandoradsargumenten till kompilatorn eller genom att lägga till #pragma warning(disable:4467) i källkoden.

    Exempel 1 (före)

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

    Exempel 1 (efter)

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

    Ibland kanske du behöver eller vill skapa en IDL-fil för att undvika att använda inaktuella ATL-attribut, som i exempelkoden nedan

    Exempel 2 (före)

    [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
    {
        // ...
    };
    

    Skapa först filen *.idl; den vc140.idl-genererade filen kan användas för att hämta en *.idl-fil som innehåller gränssnitten och anteckningarna.

    Lägg sedan till ett MIDL-steg i bygget för att se till att C++-gränssnittsdefinitionerna genereras.

    Exempel 2 IDL (efter)

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

    Använd sedan ATL direkt i implementeringsfilen, som i exempelkoden nedan.

    Genomförande av exempel 2 (efter)

    #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()
    };
    
  • Förkompilerade huvudfiler (PCH) och felmatchade #include direktiv (påverkar /Wall/WXendast )

    Tidigare versioner av kompilatorn accepterade felmatchade #include direktiv i källfiler mellan -Yc och -Yu kompileringar när PCH-filer (precompiled header) används. Kod som skrivs på det här sättet accepteras inte längre av kompilatorn. Kompilatorn utfärdar nu kompilatorvarning CC4598 för att identifiera felmatchade #include direktiv när PCH-filer används.

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

    Exempel (före):

    X.cpp (-Ycc.h)

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

    Z.cpp (-Yuc.h)

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

    Exempel (efter)

    X.cpp (-Ycc.h)

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

    Z.cpp (-Yuc.h)

    #include "a.h"
    #include "b.h" // matched order relative to X.cpp
    #include "c.h"
    
  • Förkompilerade huvudfiler (PCH) och felmatchade inkluderingskataloger (påverkar endast /Wall/WX)

    Tidigare versioner av kompilatorn accepterade felmatchade är katalog-I () kommandoradsargument till kompilatorn mellan -Yc och -Yu kompileringar när du använder förkompilerade sidhuvudfiler (PCH). Kod som skrivs på det här sättet accepteras inte längre av kompilatorn. Kompilatorn utfärdar nu kompilatorvarning CC4599 för att identifiera felmatchade kommandoradsargument för katalog (-I) när PCH-filer används.

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

    Exempel (före)

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

    Exempel (efter)

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

Ändringar i Visual Studio 2013-överensstämmelse

Kompilator

  • Det sista nyckelordet genererar nu ett olöst symbolfel där det skulle ha kompilerats tidigare:

    struct S1 {
        virtual void f() = 0;
    };
    
    struct S2 final : public S1 {
        virtual void f();
    };
    
    int main(S2 *p)
    {
        p->f();
    }
    

    I tidigare versioner utfärdades inte ett fel eftersom anropet var ett virtual anrop. Programmet skulle ändå krascha vid körning. Nu utfärdas ett länkfel eftersom klassen är känd för att vara slutgiltig. I det här exemplet, för att åtgärda felet, skulle du länka mot obj som innehåller definitionen av S2::f.

  • När du använder vänfunktioner i namnområden måste du omdeklarera funktionen vän innan du refererar till den, annars får du ett fel eftersom kompilatorn nu överensstämmer med ISO C++ Standard. Det här exemplet kompilerar till exempel inte längre:

    namespace NS {
        class C {
            void func(int);
            friend void func(C* const) {}
        };
    
        void C::func(int) {
            NS::func(this);  // error
        }
    }
    

    Om du vill korrigera den här koden deklarerar du friend funktionen:

    namespace NS {
        class C {
            void func(int);
            friend void func(C* const) {}
        };
    
        void func(C* const);  // conforming fix
    
        void C::func(int) {
            NS::func(this);
        }
    
  • C++ Standard tillåter inte explicit specialisering i en klass. Även om Microsoft C++-kompilatorn tillåter det i vissa fall genereras ett fel, till exempel i följande exempel, eftersom kompilatorn inte anser att den andra funktionen är en specialisering av den första.

    template < int N>
    class S {
    public:
        template  void f(T& val);
        template < > void f(char val);
    };
    
    template class S< 1>;
    

    Ändra den andra funktionen för att korrigera den här koden:

    template <> void f(char& val);
    
  • Kompilatorn försöker inte längre att tvetydiga de två funktionerna i följande exempel och genererar nu ett fel:

    template< typename T> void Func(T* t = nullptr);
    template< typename T> void Func(...);
    
    int main() {
        Func< int>(); // error
    }
    

    För att korrigera den här koden förtydligar du anropet:

    template< typename T> void Func(T* t = nullptr);
    template< typename T> void Func(...);
    
    int main() {
        Func< int>(nullptr); // ok
    }
    
  • Innan kompilatorn hade överensstämt med ISO C++11 skulle följande kod ha kompilerats och lett till att x resolverade till typen int.

    auto x = {0};
    int y = x;
    

    Den här koden löser x till en typ av std::initializer_list<int> och ger ett fel på nästa rad som försöker tilldela x till en typ av int. (Det finns ingen konvertering som standard.) Om du vill korrigera den här koden använder du int för att ersätta auto:

    int x = {0};
    int y = x;
    
  • Aggregerad initiering tillåts inte längre när typen av det högra värdet inte matchar den typ av vänstervärde som initieras, och ett fel utfärdas eftersom ISO C++11 Standard kräver enhetlig initiering för att fungera utan att begränsa konverteringarna. Tidigare, om en begränsad konvertering var tillgänglig, skulle en kompilatorvarning (nivå 4) C4242 ha utfärdats i stället för ett fel.

    int i = 0;
    char c = {i}; // error
    

    Du korrigerar den här koden genom att lägga till en explicit begränsad konvertering:

    int i = 0;
    char c = {static_cast<char>(i)};
    
  • Följande initiering är inte längre tillåten:

    void *p = {{0}};
    

    Använd något av följande formulär för att korrigera den här koden:

    void *p = 0;
    // or
    void *p = {0};
    
  • Namnsökningen har ändrats. Följande kod löses på olika sätt i C++-kompilatorn i Visual Studio 2012 och Visual Studio 2013:

    enum class E1 { a };
    enum class E2 { b };
    
    int main()
    {
        typedef E2 E1;
        E1::b;
    }
    

    I Visual Studio 2012 löstes uttrycket E1E1::b till ::E1 i den globala omgivningen. I Visual Studio 2013 löses E1 i uttrycket E1::b till definitionen av typedef E2 i main() och har typen ::E2.

  • Objektlayouten har ändrats. På x64 kan objektlayouten för en klass ändras från tidigare versioner. Om den har en virtual funktion men inte har någon basklass som har en virtual funktion, infogar kompilatorns objektmodell en pekare i en virtual funktionstabell efter layouten för datamedlem. Det innebär att layouten kanske inte är optimal i alla fall. I tidigare versioner skulle en optimering för x64 försöka förbättra layouten åt dig, men eftersom den inte fungerade korrekt i komplexa kodsituationer togs den bort i Visual Studio 2013. Tänk till exempel på den här koden:

    __declspec(align(16)) struct S1 {
    };
    
    struct S2 {
        virtual ~S2();
        void *p;
        S1 s;
    };
    
  • I Visual Studio 2013 är resultatet på sizeof(S2) x64 48, men i tidigare versioner utvärderas det till 32. Om du vill att detta ska utvärderas till 32 i Visual Studio 2013 C++-kompilatorn för x64 lägger du till en dummybasklass som har en virtual funktion:

    __declspec(align(16)) struct S1 {
    };
    
    struct dummy {
        virtual ~dummy() {}
    };
    struct S2 : public dummy {
        virtual ~S2();
        void *p;
        S1 s;
    };
    

    Om du vill hitta platser i koden som en tidigare version skulle ha försökt optimera använder du en kompilator från den versionen tillsammans med kompilatoralternativet /W3 och aktiverar varning C4370. Till exempel:

    #pragma warning(default:4370)
    
    __declspec(align(16)) struct S1 {
    };
    
    struct S2 {
        virtual ~S2();
        void *p;
        S1 s;
    };
    

    Innan Visual Studio 2013 skriver den här koden ut följande meddelande: "warning C4370: 'S2' : layout av klassen har ändrats från en tidigare version av kompileraren på grund av bättre packning".

    X86-kompilatorn har samma underoptimala layoutproblem i alla versioner av kompilatorn. Om den här koden till exempel kompileras för x86:

    struct S {
        virtual ~S();
        int i;
        double d;
    };
    

    Resultatet av sizeof(S) är 24. Den kan dock minskas till 16 om du använder den lösning som nämns för x64:

    struct dummy {
        virtual ~dummy() {}
    };
    
    struct S : public dummy {
        virtual ~S();
        int i;
        double d;
    };
    

Standardbibliotek

C++-kompilatorn i Visual Studio 2013 detekterar felaktiga matchningar i _ITERATOR_DEBUG_LEVEL, som implementerades i Visual Studio 2010, och RuntimeLibrary-felmatchningar. Dessa felmatchningar uppstår när kompilatoralternativ /MT (statisk utgivning), /MTd (statisk felsökning), /MD (dynamisk utgivning) och /MDd (dynamisk felsökning) blandas.

  • Om koden bekräftar den tidigare versionens simulerade aliasmallar måste du ändra den. I stället för allocator_traits<A>::rebind_alloc<U>::othermåste du till exempel säga allocator_traits<A>::rebind_alloc<U>. Även om ratio_add<R1, R2>::type inte längre är nödvändig och vi nu rekommenderar att du säger ratio_add<R1, R2>, kommer den tidigare fortfarande att kompileras eftersom ratio<N, D> måste ha en typedef av typen "typ" för ett reducerat förhållande, vilket kommer att vara samma typ om den redan är reducerad.

  • Du måste använda #include <algorithm> när du anropar std::min() eller std::max().

  • Om din befintliga kod använder den tidigare versionens simulerade omfångsuppräkningar – traditionella uppräkningar som inte är begränsade till namnområden – måste du ändra den. Om du till exempel refererade till typen std::future_status::future_statusmåste du nu säga std::future_status. De flesta koderna påverkas dock inte, till exempel std::future_status::ready kompileras fortfarande.

  • explicit operator bool() är striktare än operatorn unspecified-bool-type(). explicit operator bool() tillåter explicita konverteringar till bool , till exempel givet shared_ptr<X> sp, både static_cast<bool>(sp) och bool b(sp) är giltiga – och boolesktestbara "kontextuella konverteringar" till bool – till exempel if (sp), !spvad sp && som helst. Förbjuder dock explicit operator bool() implicita konverteringar till bool, så du kan inte säga bool b = sp; och med en bool-returtyp kan du inte säga return sp.

  • Nu när verkliga variadic-mallar implementeras har _VARIADIC_MAX och relaterade makron ingen effekt. Om du fortfarande definierar _VARIADIC_MAX ignoreras det. Om du har använt våra makromaskiner som är avsedda att stödja simulerade variadiska mallar på något annat sätt än avsett måste du ändra din kod.

  • Förutom vanliga nyckelord förbjuder C++ standardbibliotekshuvuden nu makrobytet av kontextkänsliga nyckelord åsidosättning och slutlig.

  • reference_wrapper, ref()och cref() förbjuder nu bindning till temporära objekt.

  • <random> framtvingar nu strikt sina kompileringstidsförutsättningar.

  • Olika egenskaper för C++-standardbibliotekstyp har förhandsvillkoret "T ska vara en fullständig typ". Även om kompilatorn nu tillämpar den här förutsättningen striktare kanske den inte framtvingar den i alla situationer. (Eftersom förhandsvillkorsöverträdelser för C++ StandardBibliotek utlöser odefinierat beteende garanterar standardinställningen inte verkställighet.)

  • C++-standardbiblioteket stödjer inte /clr:oldSyntax.

  • C++11-specifikationen för common_type<> hade oväntade och oönskade konsekvenser; i synnerhet får den common_type<int, int>::type att returnera int&&. Kompilatorn implementerar därför den föreslagna lösningen för biblioteksarbetsgruppens problem 2141, som returnerar common_type<int, int="">::typeint.

    Som en bieffekt av denna ändring fungerar inte längre identitetsfallet (common_type<T> resulterar inte alltid i typ T). Det här beteendet överensstämmer med den föreslagna lösningen, men den bryter all kod som förlitade sig på det tidigare beteendet.

    Om du behöver ett identitetstypdrag ska du inte använda den icke-standard std::identity som har definierats i <type_traits> eftersom den inte fungerar för <void>. Implementera i stället ditt eget identitetstypdrag som passar dina behov. Här är ett exempel:

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

MFC och ATL

  • Endast Visual Studio 2013: MFC MBCS-biblioteket ingår inte i Visual Studio eftersom Unicode är så populärt och användningen av MBCS har minskat avsevärt. Den här ändringen håller även MFC mer anpassad med själva Windows SDK eftersom många av de nya kontrollerna och meddelandena är endast Unicode. Men om du måste fortsätta att använda MFC MBCS-biblioteket kan du ladda ned det från Microsoft Download Center på Multibyte MFC-biblioteket för Visual Studio 2013. Visual C++ Redistributable Package innehåller fortfarande det här biblioteket. (Obs! MBCS DLL ingår i C++-installationskomponenterna i Visual Studio 2015 och senare).

  • Tillgängligheten för MFC-menyfliksområdet har ändrats. I stället för en arkitektur på en nivå finns det nu en hierarkisk arkitektur. Du kan fortfarande använda det gamla beteendet genom att anropa CRibbonBar::EnableSingleLevelAccessibilityMode().

  • CDatabase::GetConnect -metoden tas bort. För att förbättra säkerheten lagras anslutningssträngen nu krypterad och dekrypteras endast efter behov. det kan inte returneras som oformaterad text. Strängen kan erhållas med hjälp av CDatabase::Dump metoden.

  • Signaturen för CWnd::OnPowerBroadcast har ändrats. Signaturen för den här meddelandehanteraren ändras för att ta en LPARAM som den andra parametern.

  • Signaturer ändras för att passa meddelandehanterare. Parameterlistorna för följande funktioner har ändrats för att använda nyligen tillagda ON_WM_* meddelandehanterare:

    • CWnd::OnDisplayChange har ändrats till (UINT, int, int) i stället för (WPARAM, LPARAM) så att det nya ON_WM_DISPLAYCHANGE makrot kan användas i meddelandekartan.

    • CFrameWnd::OnDDEInitiate har ändrats till (CWnd*, UINT, UNIT) i stället för (WPARAM, LPARAM) så att det nya ON_WM_DDE_INITIATE makrot kan användas i meddelandekartan.

    • CFrameWnd::OnDDEExecute har ändrats till (CWnd*, HANDLE) i stället för (WPARAM, LPARAM) så att det nya ON_WM_DDE_EXECUTE makrot kan användas på meddelandekartan.

    • CFrameWnd::OnDDETerminate har ändrats till (CWnd*) som parameter i stället för (WPARAM, LPARAM) så att det nya ON_WM_DDE_TERMINATE makrot kan användas i meddelandekartan.

    • CMFCMaskedEdit::OnCut har ändrats till inga parametrar i stället för (WPARAM, LPARAM) så att det nya ON_WM_CUT makrot kan användas i meddelandekartan.

    • CMFCMaskedEdit::OnClear har ändrats till inga parametrar i stället för (WPARAM, LPARAM) så att det nya ON_WM_CLEAR makrot kan användas i meddelandekartan.

    • CMFCMaskedEdit::OnPaste har ändrats till inga parametrar i stället för (WPARAM, LPARAM) så att det nya ON_WM_PASTE makrot kan användas i meddelandekartan.

  • #ifdef direktiv i MFC-huvudfilerna tas bort. Många #ifdef direktiv i MFC-huvudfilerna som rör versioner av Windows (WINVER < 0x0501) som inte stöds tas bort.

  • ATL DLL (atl120.dll) tas bort. ATL tillhandahålls nu som rubriker och ett statiskt bibliotek (atls.lib).

  • Atlsd.lib, atlsn.lib och atlsnd.lib tas bort. Atls.lib har inte längre teckenuppsättningsberoenden eller kod som är specifika för felsökning/lansering. Eftersom det fungerar på samma sätt för Unicode/ANSI och felsökning/version krävs endast en version av biblioteket.

  • ATL/MFC Trace-verktyget tas bort tillsammans med ATL DLL och spårningsmekanismen förenklas. Konstruktorn CTraceCategory tar nu en parameter (kategorinamnet) och TRACE-makrona anropar CRT-felsökningsrapporteringsfunktionerna.

Brytande ändringar i Visual Studio 2012

Kompilator

  • Kompilatoralternativet /Yl har ändrats. Kompilatorn använder som standard det här alternativet, vilket kan leda till LNK2011 fel under vissa förhållanden. För mer information, se /Yl (Mata in PCH-referens för felsökningsbiblioteket).

  • I kod som kompileras med /clr, definierar nyckelordet class enum en C++11-uppräkning, inte en CLR-uppräkning (Common Language Runtime). Om du vill definiera en CLR-uppräkning måste du vara tydlig med dess tillgänglighet.

  • Använd nyckelordet "template" för att uttryckligen klargöra ett beroende namn i enlighet med C++-standardens krav. I följande exempel är nyckelordet för den markerade mallen obligatoriskt för att lösa tvetydigheten. Mer information finns i Namnmatchning för beroende typer.

    template < typename X = "", typename = "" AY = "">
    struct Container { typedef typename AY::template Rebind< X> ::Other AX; };
    
  • Konstant uttryck av typen float tillåts inte längre som ett mallargument, som du ser i följande exempel.

    template<float n=3.14>
    struct B {};  // error C2993: 'float': illegal type for non-type template parameter 'n'
    
  • Kod som kompileras med kommandoradsalternativet /GS och har en off-by-one sårbarhet kan leda till att processen termineras vid körtid, vilket visas i följande pseudokod-exempel.

    char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminate
    
  • Standardarkitekturen för x86-versioner ändras till SSE2. Kompilatorn kan därför avge SSE-instruktioner och använder XMM-registren för att utföra flyttalsberäkningar. Om du vill återgå till tidigare beteende använder du kompilatorflaggan /arch:IA32 för att ange arkitekturen som IA32.

  • Kompilatorn kan utfärda varningar Kompilatorvarning (nivå 4) C4703 och C4701 där den tidigare inte gjorde det. Kompilatorn tillämpar starkare kontroller för användning av uninitialiserade lokala variabler av pekartyp.

  • När den nya länkflaggan /HIGHENTROPYVA har angetts orsakar Windows 8 vanligtvis minnesallokeringar för att returnera en 64-bitars adress. (Före Windows 8 returnerade sådana allokeringar oftare adresser som var mindre än 2 GB.) Den här ändringen kan exponera pekartunkeringsbuggar i befintlig kod. Som standard är den här växeln på. Om du vill inaktivera det här beteendet anger du /HIGHENTROPYVA:NO.

  • Den hanterade kompilatorn (Visual Basic/C#) har också stöd /HIGHENTROPYVA för hanterade versioner. Men i det här fallet är /HIGHENTROPYVAswitch inaktiverad som standard.

IDE

  • Även om vi rekommenderar att du inte skapar Windows Forms-program i C++/CLI, stöds underhåll av befintliga C++/CLI-gränssnittsprogram. Om du måste skapa ett Windows Forms-program eller något annat .NET-användargränssnittsprogram använder du C# eller Visual Basic. Använd endast C++/CLI i samverkanssyfte.

Bibliotek för parallella mönster och samtidighetskörningsbibliotek

Uppräkningen SchedulerType av UmsThreadDefault är inaktuell. Specifikationen av UmsThreadDefault genererar en inaktuell varning och mappar internt tillbaka till ThreadScheduler.

Standardbibliotek

  • Efter en genombrottsändring mellan C++98/03- och C++11-standarderna går det vanligtvis inte att använda explicita mallargument för att anropa make_pair() – som i make_pair<int, int>(x, y) – i Visual C++ i Visual Studio 2012. Lösningen är att alltid anropa make_pair() utan explicita mallargument – som i make_pair(x, y). Att tillhandahålla explicita mallargument motverkar funktionens syfte. Om du behöver exakt kontroll över den resulterande typen använder du pair i stället för make_pair – som i pair<short, short>(int1, int2).

  • En annan icke-bakåtkompatibel ändring mellan C++98/03- och C++11-standarderna: När A kan implicit konverteras till B och B kan implicit konverteras till C, men A inte kan implicit konverteras till C, tillät C++98/03 och Visual Studio 2010 pair<A, X> att konverteras (implicit eller explicit) till pair<C, X>. (Den andra typen, X, är inte av intresse här och är inte specifik för den första typen i paret.) C++-kompilatorn i Visual Studio 2012 identifierar att A inte implicit kan konverteras till C och tar bort parkonverteringen från överbelastningsupplösning. Den här ändringen är positiv för många scenarier. Till exempel kommer överlagring func(const pair<int, int>&) och func(const pair<string, string>&) och att anropa func() med pair<const char *, const char *> att kompilera med den här ändringen. Den här ändringen bryter dock kod som förlitade sig på aggressiva parkonverteringar. Sådan kod kan vanligtvis åtgärdas genom att utföra en del av konverteringen explicit, till exempel genom att skicka make_pair(static_cast<B>(a), x) till en funktion som förväntar sig pair<C, X>.

  • Simulerade variadmallar i Visual Studio 2010 – till exempel make_shared<T>(arg1, arg2, argN)– upp till en gräns på 10 argument genom att utrota överlagringar och specialiseringar med maskiner för förprocessorer. I Visual Studio 2012 minskas den här gränsen till fem argument för att förbättra kompileringstiderna och kompilatorns minnesförbrukning för de flesta användare. Du kan dock ange den tidigare gränsen genom att uttryckligen definiera _VARIADIC_MAX som 10, hela projektet.

  • C++11 17.6.4.3.1 [macro.names]/2 förbjuder makrobyte av nyckelord när C++ Standard Library-huvuden inkluderas. Rubrikerna genererar nu kompilatorfel om de identifierar makro-ersatta nyckelord. (Genom att definiera _ALLOW_KEYWORD_MACROS kan sådan kod kompileras, men vi avråder starkt från den användningen.) Som ett undantag tillåts makroformen new av som standard, eftersom rubrikerna skyddar sig fullständigt med hjälp#pragma push_macro("new")/#undef new/#pragma pop_macro("new") av . Att definiera _ENFORCE_BAN_OF_MACRO_NEW gör exakt vad namnet antyder.

  • För att implementera olika optimeringar och felsökningskontroller bryter C++ Standard Library-implementeringen avsiktligt binär kompatibilitet mellan versioner av Visual Studio (2005, 2008, 2010, 2012). När C++-standardbiblioteket används förbjuder det blandning av objektfiler och statiska bibliotek som kompileras med hjälp av olika versioner i en binär fil (EXE eller DLL) och förbjuder överföring av C++ standardbiblioteksobjekt mellan binärfiler som kompileras med hjälp av olika versioner. Blandning av objektfiler och statiska bibliotek (med hjälp av C++-standardbiblioteket som kompilerades med hjälp av Visual Studio 2010 med de som kompilerades med hjälp av C++-kompilatorn i Visual Studio 2012 genererar länkfel om _MSC_VER matchningsfel, där _MSC_VER är makrot som innehåller kompilatorns huvudversion (1700 för Visual C++ i Visual Studio 2012). Den här kontrollen kan inte identifiera DLL-blandning och kan inte identifiera blandning som omfattar Visual Studio 2008 eller tidigare.

  • Förutom att identifiera _ITERATOR_DEBUG_LEVEL missmatchningar, som implementerades i Visual Studio 2010, upptäcker C++-kompilatorn i Visual Studio 2012 missmatchningar i körbiblioteket. Dessa matchningar uppstår när kompilatoralternativen /MT (statisk version), /MTd (statisk felsökning), /MD (dynamisk version) och /MDd (dynamisk felsökning) blandas.

  • operator<(), operator>(), operator<=() och operator>=() var tidigare tillgängliga för std::unordered_map- och stdext::hash_map-familjerna av containrar, även om deras implementeringar inte var användbara. Dessa icke-standardoperatorer har tagits bort i Visual C++ i Visual Studio 2012. Dessutom har genomförandet av operator==() och operator!=() för std::unordered_map-familjen utökats för att täcka stdext::hash_map-familjen. (Vi rekommenderar att du undviker att använda stdext::hash_map familjen i ny kod.)

  • C++11 22.4.1.4 [locale.codecvt] anger detta codecvt::length() och codecvt::do_length() bör ta modifierbara stateT& parametrar, men Visual Studio 2010 tog const stateT&. C++-kompilatorn i Visual Studio 2012 tar stateT& som föreskrivs av standarden. Den här skillnaden är betydande för alla som försöker åsidosätta den virtuella funktionen do_length().

CRT

  • C Runtime (CRT)-heapen, som används för new och malloc(), är inte längre privat. CRT använder nu process-heapen. Det innebär att heapen inte förstörs när en DLL avladdas, så DLL:er som länkar statiskt till CRT måste se till att minnet som allokerats av DLL-koden rengörs innan DLL:en avladdas.

  • Funktionen iscsymf() hävdar med negativa värden.

  • Structen threadlocaleinfostruct har ändrats för att anpassa ändringarna till nationella funktioner.

  • CRT-funktioner som har motsvarande inbyggda funktioner, till exempel memxxx(), strxxx() tas bort från intrin.h. Om du bara har inkluderat intrin.h för dessa funktioner måste du nu inkludera motsvarande CRT-huvuden.

MFC och ATL

  • Stöd för fusion har tagits bort (afxcomctl32.h); Därför har alla metoder som definierats i <afxcomctl32.h> tagits bort. Huvudfiler <afxcomctl32.h> och <afxcomctl32.inl> har tagits bort.

  • Ändrade namnet på CDockablePane::RemoveFromDefaultPaneDividier till CDockablePane::RemoveFromDefaultPaneDivider.

  • Ändrade signaturen CFileDialog::SetDefExt för att använda LPCTSTR, därför påverkas Unicode-versioner.

  • Föråldrade ATL-spårningskategorier har tagits bort.

  • Ändrade signaturen för CBasePane::MoveWindow så att den tar en const CRect.

  • Ändrade signaturen för CMFCEditBrowseCtrl::EnableBrowseButton.

  • Tog bort m_fntTabs och m_fntTabsBold från CMFCBaseTabCtrl.

  • Lade till en parameter i konstruktorerna CMFCRibbonStatusBarPane . (Det är en standardparameter, så den är inte källbrytande.)

  • Lade till en parameter i CMFCRibbonCommandsListBox konstruktorn. (Det är en standardparameter, så den är inte källbrytande.)

  • Tog bort API:et AFXTrackMouse (och relaterad tidsinställd process). Använd Win32-API TrackMouseEvent :et i stället.

  • Lade till en parameter i CFolderPickerDialog konstruktorn. (Det är en standardparameter, så den är inte källbrytande.)

  • CFileStatus strukturstorleken har ändrats: Medlemmen m_attribute har ändrats från BYTE till DWORD (för att matcha värdet som returneras från GetFileAttributes).

  • CRichEditCtrl och CRichEditView använd MSFTEDIT_CLASS (RichEdit 4.1-kontroll) i stället för RICHEDIT_CLASS (RichEdit 3.0-kontroll) i Unicode-versioner.

  • Har tagits bort AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground eftersom det alltid är SANT i Windows Vista, Windows 7 och Windows 8.

  • Har tagits bort AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable eftersom det alltid är SANT i Windows Vista, Windows 7 och Windows 8.

  • Tog bort AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea. Anropa Windows API direkt i Windows Vista, Windows 7 och Windows 8.

  • Tog bort AFX_GLOBAL_DATA::DwmDefWindowProc. Anropa Windows API direkt i Windows Vista, Windows 7 och Windows 8.

  • Bytte namn på AFX_GLOBAL_DATA::DwmIsCompositionEnabled till IsDwmCompositionEnabled för att eliminera namnkollision.

  • Ändrade identifierare för ett antal interna MFC-timers och flyttade definitionerna till afxres.h (AFX_TIMER_ID_*).

  • Ändrade signaturen OnExitSizeMove för metoden för att överensstämma med makrot ON_WM_EXITSIZEMOVE:

    • CFrameWndEx

    • CMDIFrameWndEx

    • CPaneFrameWnd

  • Ändrade namnet och signaturen för OnDWMCompositionChanged för att överensstämma med makrot ON_WM_DWMCOMPOSITIONCHANGED:

    • CFrameWndEx

    • CMDIFrameWndEx

    • CPaneFrameWnd

  • Ändrade signaturen OnMouseLeave för metoden för att överensstämma med makrot ON_WM_MOUSELEAVE:

    • CMFCCaptionBar

    • CMFCColorBar

    • CMFCHeaderCtrl

    • CMFCProperySheetListBox

    • CMFCRibbonBar

    • CMFCRibbonPanelMenuBar

    • CMFCRibbonRichEditCtrl

    • CMFCSpinButtonCtrl

    • CMFCToolBar ErsättDennaText

    • CMFCToolBarComboBoxEdit

    • CMFCToolBarEditCtrl

    • CMFCAutoHideBar

  • Ändrade signaturen OnPowerBroadcast för för att överensstämma med makrot ON_WM_POWERBROADCAST:

    • CFrameWndEx

    • CMDIFrameWndEx

  • Har ändrat signaturen OnStyleChanged för för att överensstämma med makrot ON_WM_STYLECHANGED:

    • CMFCListCtrl

    • CMFCStatusBar

  • Den interna metoden FontFamalyProcFonts har bytt namn till FontFamilyProcFonts.

  • Flera globala statiska CString objekt har tagits bort för att eliminera minnesläckor i vissa situationer (ersatta med #defines) och följande klassmedlemsvariabler:

    • CKeyBoardManager::m_strDelimiter

    • CMFCPropertyGridProperty::m_strFormatChar

    • CMFCPropertyGridProperty::m_strFormatShort

    • CMFCPropertyGridProperty::m_strFormatLong

    • CMFCPropertyGridProperty::m_strFormatUShort

    • CMFCPropertyGridProperty::m_strFormatULong

    • CMFCPropertyGridProperty::m_strFormatFloat

    • CMFCPropertyGridProperty::m_strFormatDouble

    • CMFCToolBarImages::m_strPngResType

    • CMFCPropertyGridProperty::m_strFormat

  • Ändrade signaturen för CKeyboardManager::ShowAllAccelerators och tog bort parametern för acceleratoravgränsare.

  • Lade till CPropertyPage::GetParentSheet, och i CPropertyPage-klassen anropar du nu detta istället för GetParent för att hämta rätt överordnat bladfönster, som kan vara det överordnade eller ett förfädersfönster till CPropertyPage. Du kan behöva ändra koden för att anropa GetParentSheet i stället för GetParent.

  • Åtgärdade obalanserad #pragma warning(push) i ATLBASE.H, vilket gjorde att varningar inaktiverades felaktigt. Dessa varningar är nu aktiverade korrekt efter ATLBASE. H har parsats.

  • Flyttade D2D-relaterade metoder från AFX_GLOBAL_DATA till _AFX_D2D_STATE:

    • GetDirectD2dFactory

    • GetWriteFactory

    • GetWICFactory

    • InitD2D

    • ReleaseD2DRefs

    • IsD2DInitialized

    • D2D1MakeRotateMatrix

    • I stället för att anropa till exempel afxGlobalData.IsD2DInitialized, anropa AfxGetD2DState->IsD2DInitialized.

  • Tog bort föråldrad ATL*. CPP-filer från mappen \atlmfc\include\.

  • Flyttade afxGlobalData initieringen till på begäran istället för under CRT-initieringsfasen, för att uppfylla DLLMain krav.

  • RemoveButtonByIndex Metoden har lagts till i CMFCOutlookBarPane klassen.

  • Korrigerade CMFCCmdUsageCount::IsFreqeuntlyUsedCmd till IsFrequentlyUsedCmd.

  • Korrigerade flera instanser av RestoreOriginalstate till RestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).

  • Oanvända metoder har tagits bort från CDockablePane: SetCaptionStyle, IsDrawCaption, IsHideDisabledButtons, GetRecentSiblingPaneInfooch CanAdjustLayout.

  • Tog bort CDockablePane statiska medlemsvariabler m_bCaptionText och m_bHideDisabledButtons.

  • Lade till en åsidosättningsmetod DeleteString i CMFCFontComboBox.

  • Oanvända metoder har tagits bort från CPane: GetMinLength och IsLastPaneOnLastRow.

  • Har bytt CPane::GetDockSiteRow(CDockingPanesRow *) namn till CPane::SetDockSiteRow.

Ändringar som bryter kompatibilitet i Visual Studio 2010

Kompilator

  • Nyckelordet auto har en ny standard betydelse. Eftersom användningen av den gamla innebörden är sällsynt påverkas de flesta program inte av den här ändringen.

  • Det nya static_assert nyckelordet introduceras, vilket orsakar en namnkonflikt om det redan finns en identifierare med det namnet i koden.

  • Stöd för den nya lambda-notationen utesluter stöd för kodning av ett ociterat GUID i ett IDL uuid-attribut.

  • .NET Framework 4 introducerar begreppet skadade tillståndsundanstag, som är undantag som lämnar en process i ett oåterkalleligt skadat tillstånd. Som standardinställning kan du inte fånga ett skadad tillståndsundantag, även med kompileringsalternativet /EHa som fångar alla andra undantag. Använd __try-__except-instruktioner för att uttryckligen fånga ett skadat tillståndsfel. Du kan också använda attributet [HandledProcessCorruptedStateExceptions] för att aktivera en funktion för att fånga skadade tillståndsundantag. Den här ändringen påverkar främst systemprogrammerare som kan behöva fånga ett undantag för skadat tillstånd. De åtta undantagen är STATUS_ACCESS_VIOLATION, STATUS_STACK_OVERFLOW, EXCEPTION_ILLEGAL_INSTRUCTION, EXCEPTION_IN_PAGE_ERROR, EXCEPTION_INVALID_DISPOSITION, EXCEPTION_NONCONTINUABLE_EXCEPTION, EXCEPTION_PRIV_INSTRUCTION, STATUS_UNWIND_CONSOLIDATE. Mer information om dessa undantag finns i makrot GetExceptionCode .

  • Det ändrade /GS kompileringsalternativet skyddar mot buffertöverskridanden mer omfattande än i tidigare versioner. Den här versionen kan infoga ytterligare säkerhetskontroller i stacken som kan minska prestandan. Använd det nya __declspec(safebuffers) nyckelordet för att instruera kompilatorn att inte infoga säkerhetskontroller för en viss funktion.

  • Om du kompilerar med kompileringsalternativen /GL/clr (hela programoptimering) och /GL (Common Language Runtime-kompilering) ignoreras alternativet. Den här ändringen gjordes eftersom kombinationen av kompilatoralternativ gav liten fördel. Som ett resultat av den här ändringen förbättras byggets prestanda.

  • Som standard inaktiveras stöd för trigrafer i Visual Studio 2010. Använd kompileringsalternativet /Zc:trigraphs för att aktivera stöd för trigrafer. En trigraf består av två på varandra följande frågetecken ("??") följt av ett unikt tredje tecken. Kompilatorn ersätter en trigraf med motsvarande skiljetecken. Kompilatorn ersätter till exempel trigrafen ??= med tecknet #. Använd trigrafer i C-källfiler som använder en teckenuppsättning som inte innehåller praktiska grafiska representationer för vissa skiljetecken.

  • Länkaren stöder inte längre optimering för Windows 98. Alternativet /OPT (Optimeringar) skapar ett kompileringstidsfel om du anger /OPT:WIN98 eller /OPT:NOWIN98.

  • Standardalternativen för kompilatorn som anges av systemegenskaperna RuntimeLibrary och DebugInformationFormat har ändrats. Som standard anges dessa byggegenskaper i projekt som skapas av Visual C++ versioner 7.0 till 10.0. Om du migrerar ett projekt som skapades av Visual C++ 6.0 bör du överväga om du vill ange ett värde för dessa egenskaper.

  • I Visual Studio 2010, RuntimeLibrary = MultiThreaded (/MD) och DebugInformationFormat = ProgramDatabase (/Zi). I Visual C++ 9.0, RuntimeLibrary = Flertrådad (/MT) och DebugInformationFormat = Inaktiverad.

CLR (Common Language Runtime)

  • Microsoft C# och Visual Basic-kompilatorerna kan nu skapa utan en primär interop-sammansättning (ingen PIA). En sammansättning utan PIA kan använda sig av COM-typer utan att distribuera den relevanta primära interop-samlingen. När du använder no-PIA-sammansättningar som skapats av Visual C# eller Visual Basic måste du referera till PIA-sammansättningen i kompileringskommandot innan du refererar till någon no-PIA-sammansättning som använder biblioteket.

Visual Studio C++-projekt och MSBuild

  • Visual Studio C++-projekt baseras nu på VERKTYGET MSBuild. Därför använder projektfiler ett nytt XML-filformat och ett .vcxproj filsuffix. Visual Studio 2010 konverterar automatiskt projektfiler från tidigare versioner av Visual Studio till det nya filformatet. Ett befintligt projekt påverkas om det beror på det tidigare byggverktyget, VCBUILD.exeeller projektfilsuffixet .vcproj.

  • I tidigare versioner stödde Visual C++ den sena utvärderingen av egenskapsblad. Ett överordnat egenskapsblad kan till exempel importera ett underordnat egenskapsblad, och den överordnade kan använda en variabel som definierats i det underordnade objektet för att definiera andra variabler. Försenad utvärdering gjorde det möjligt för föräldern att använda barnvariabeln redan innan barnets egenskapsblad importerades. I Visual Studio 2010 kan en projektdokumentvariabel inte användas innan den definieras eftersom MSBuild endast stöder tidig utvärdering.

IDE

  • Dialogrutan för programavslut avslutar inte längre ett program. I tidigare versioner, när abort() funktionen eller terminate() stängde detaljhandelsversionen av ett program, visade C Run-Time-biblioteket ett meddelande om programavslut i ett konsolfönster eller en dialogruta. Meddelandet sa delvis: "Det här programmet har begärt att Runtime ska avsluta det på ett ovanligt sätt. Kontakta programmets supportteam för mer information." Meddelandet om programavslut var redundant eftersom Windows senare visade den aktuella avslutningshanteraren, vilket vanligtvis var dialogrutan Windows Error Reporting (Dr. Watson) eller Visual Studio-felsökningsprogrammet. Från och med Visual Studio 2010 visas inte meddelandet i C Run-Time-biblioteket. Dessutom förhindrar körmiljön att programmet avslutas innan en felsökare startar. Det här är en kritisk ändring bara om du förlitar dig på det tidigare beteendet av programavslutsmeddelandet.

  • Specifikt för Visual Studio 2010 fungerar inte IntelliSense för C++/CLI-kod eller -attribut, Hitta alla referenser fungerar inte för lokala variabler och Kodmodellen hämtar inte typnamn från importerade sammansättningar eller löser typer till sina fullständigt kvalificerade namn.

Bibliotek

  • Klassen SafeInt ingår i Visual C++ och finns inte längre i en separat nedladdning. Det här är bara en icke-bakåtkompatibel ändring om du har utvecklat en klass med namnet "SafeInt".

  • Distributionsmodellen för bibliotek använder inte längre manifest för att hitta en viss version av ett dynamiskt länkbibliotek. I stället innehåller namnet på varje dynamiskt länkbibliotek dess versionsnummer och du använder det namnet för att hitta biblioteket.

  • I tidigare versioner av Visual Studio kunde du återskapa körtidsbiblioteken. Visual Studio 2010 har inte längre stöd för att skapa egna kopior av C-körningsbiblioteksfilerna.

Standardbibliotek

  • Huvudet <iterator> inkluderas inte längre automatiskt av många andra huvudfiler. Inkludera i stället rubriken explicit om du behöver stöd för de fristående iteratorer som definierats i rubriken. Ett befintligt projekt påverkas om det beror på det tidigare byggverktyget, VCBUILD.exeeller projektfilsuffixet .vcproj.iterator.

  • I rubriken <algorithm> tas funktionerna checked_* och unchecked_* bort. Och i <iterator>>-rubriken tas checked_iterator-klassen bort och unchecked_array_iterator-klassen har lagts till.

  • Konstruktorn CComPtr::CComPtr(int) tas bort. Konstruktorn tillät att ett CComPtr objekt konstruerades från NULL-makrot, men var onödigt och tillät meningslösa konstruktioner från heltal som inte är noll.

    A CComPtr kan fortfarande konstrueras från NULL, som definieras som 0, men misslyckas om det konstrueras från ett annat heltal än literal 0. Använd nullptr i stället.

  • Följande ctype medlemsfunktioner har tagits bort: ctype::_Do_narrow_s, ctype::_Do_widen_s, ctype::_narrow_s, ctype::_widen_s. Om ett program använder någon av dessa medlemsfunktioner måste du ersätta den med motsvarande icke-säkra version: ctype::do_narrow, ctype::do_widen, ctype::narrow, ctype::widen.

CRT-, MFC- och ATL-bibliotek

  • Stöd har tagits bort för användare för att skapa CRT-, MFC- och ATL-biblioteken. Till exempel tillhandahålls ingen lämplig NMAKE-fil. Användarna har dock fortfarande åtkomst till källkoden för dessa bibliotek. Och ett dokument som beskriver de MSBuild-alternativ som Microsoft använder för att skapa dessa bibliotek kommer förmodligen att publiceras i en Visual C++ Team-blogg.

  • MFC-stöd för IA64 har tagits bort. Stöd för CRT och ATL på IA64 tillhandahålls dock fortfarande.

  • Ordningstal återanvänds inte längre i MFC-moduldefinitionsfiler (.def). Den här ändringen innebär att ordningstalen inte skiljer sig mellan mindre versioner, och binär kompatibilitet för servicepaket och snabbkorrigeringsversioner kommer att förbättras.

  • En ny virtuell funktion har lagts till i CDocTemplate klassen. Den nya virtuella funktionen är CDocTemplate Class. Den tidigare versionen av OpenDocumentFile hade två parametrar. Den nya versionen har tre parametrar. För att stödja omstartshanteraren måste alla klasser som härleds från CDocTemplate implementera den version som har tre parametrar. Den nya parametern är bAddToMRU.

Makron och miljövariabler

  • Miljövariabeln __MSVCRT_HEAP_SELECT stöds inte längre. Den här miljövariabeln tas bort och det finns ingen ersättning.

Referens för Microsoft Macro Assembler

  • Flera direktiv har tagits bort från Microsoft Macro Assembler-referenskompilatorn. De borttagna direktiven är .186, .286, .286P, .287, .8086och .8087.NO87.

Icke-bakåtkompatibla ändringar i Visual Studio 2008

Kompilator

  • Plattformarna Windows 95, Windows 98, Windows ME och Windows NT stöds inte längre. Dessa operativsystem har tagits bort från listan över målplattformar.

  • Kompilatorn stöder inte längre flera attribut som är direkt associerade med ATL Server. Följande attribut stöds inte längre:

    • prestandaräknare

    • perf_object

    • perfmon (prestandaövervakningsverktyget)

    • förfrågningshanterare

    • SOAP-handler

    • SOAP-huvud

    • soap_metod

    • taggnamn

Visual Studio C++-projekt

  • När du uppgraderar projekt från tidigare versioner av Visual Studio kan du behöva ändra WINVER och _WIN32_WINNT makron så att de är större än eller lika med 0x0500.

  • Från och med Visual Studio 2008 har den nya projektguiden inget alternativ för att skapa ett C++ SQL Server-projekt. SQL Server-projekt som skapats med hjälp av en tidigare version av Visual Studio kompileras fortfarande och fungerar korrekt.

  • Windows API-huvudfilen Winable.h har tagits bort. Inkludera Winuser.h i stället.

  • Windows API-biblioteket Rpcndr.lib har tagits bort. Länka med rpcrt4.lib i stället.

CRT

  • Stöd för Windows 95, Windows 98, Windows Millennium Edition och Windows NT 4.0 har tagits bort.

  • Följande globala variabler har tagits bort:

    • _osplatform

    • _osver

    • _winmajor

    • _winminor

    • _winver

  • Följande funktioner har tagits bort. Använd Windows API-funktionerna GetVersion eller GetVersionEx i stället:

    • _get_osplatform

    • _get_osver

    • _get_winmajor

    • _get_winminor

    • _get_winver

  • Syntaxen för SAL-anteckningar har ändrats. Mer information finns i SAL-anteckningar.

  • IEEE-filtret stöder nu instruktionsuppsättningen SSE 4.1. Mer information finns i _fpieee_flt.

  • De C Run-Time-bibliotek som levereras med Visual Studio är inte längre beroende av systemets DLL-msvcrt.dll.

Standardbibliotek

  • Stöd för Windows 95, Windows 98, Windows Millennium Edition och Windows NT 4.0 har tagits bort.

  • När du kompilerar i felsökningsläge med _HAS_ITERATOR_DEBUGGING definierat (ersatt av _ITERATOR_DEBUG_LEVEL efter Visual Studio 2010), kommer ett program nu att kontrollera när en iterator försöker öka eller minska gränsen för den underliggande containern.

  • Medlemsvariabeln c för stackklassen är nu skyddad. Tidigare förklarades den här medlemsvariabeln offentlig.

  • Beteendet av money_get::do_get har ändrats. Tidigare, när du analyserade en monetär mängd med fler bråksiffror än vad som behövs av frac_digits, brukade do_get konsumera alla. do_get slutar nu analys efter att ha analyserat som mest frac_digits tecken.

ATL

  • ATL kan inte skapas utan ett beroende av CRT. I tidigare versioner av Visual Studio kan du använda #define ATL_MIN_CRT för att göra ett ATL-projekt minimalt beroende av CRT. I Visual Studio 2008 är alla ATL-projekt minimalt beroende av CRT oavsett om ATL_MIN_CRT har definierats.

  • ATL Server-kodbasen har släppts som ett delat källkodsprojekt på CodePlex och är inte installerad som en del av Visual Studio. Datakodnings- och avkodningsklasser från atlenc.h och verktygsfunktioner och klasser från atlutil.h och atlpath.h har sparats och ingår nu i ATL-biblioteket. Flera filer som är associerade med ATL Server ingår inte längre i Visual Studio.

  • Vissa funktioner ingår inte längre i DLL:n. De finns fortfarande i importbiblioteket. Detta påverkar inte kod som använder funktionerna statiskt. Det påverkar endast den kod som använder dessa funktioner dynamiskt.

  • Makrona PROP_ENTRY och PROP_ENTRY_EX har föråldrats och ersatts med makron PROP_ENTRY_TYPE och PROP_ENTRY_TYPE_EX av säkerhetsskäl.

Delade ATL/MFC-klasser

  • ATL kan inte skapas utan ett beroende av CRT. I tidigare versioner av Visual Studio kan du använda #define ATL_MIN_CRT för att göra ett ATL-projekt minimalt beroende av CRT. I Visual Studio 2008 är alla ATL-projekt minimalt beroende av CRT oavsett om ATL_MIN_CRT har definierats.

  • ATL Server-kodbasen har släppts som ett delat källkodsprojekt på CodePlex och är inte installerad som en del av Visual Studio. Datakodnings- och avkodningsklasser från atlenc.h och verktygsfunktioner och klasser från atlutil.h och atlpath.h har sparats och ingår nu i ATL-biblioteket. Flera filer som är associerade med ATL Server ingår inte längre i Visual Studio.

  • Vissa funktioner ingår inte längre i DLL:n. De finns fortfarande i importbiblioteket. Detta påverkar inte kod som använder funktionerna statiskt. Det påverkar endast den kod som använder dessa funktioner dynamiskt.

MFC

  • CTime Klass: Klassen CTime accepterar nu datum från 1/1/1900 C.E. i stället för 1/1/1970 C.E.

  • Tabbordning för kontroller i MFC-dialogrutor: Rätt flikordning för flera kontroller i en MFC-dialogruta störs om en MFC ActiveX-kontroll infogas i tabbordningen. Den här ändringen korrigerar problemet.

    Skapa till exempel ett MFC-dialogprogram som har en ActiveX-kontroll och flera redigeringskontroller. Placera ActiveX-kontrollen i mitten av flikordningen för redigeringskontrollerna. Starta programmet, klicka på en redigeringskontroll vars flikordning är efter ActiveX-kontrollen och ta sedan fliken. Före den här ändringen gick fokus till redigeringskontrollen efter ActiveX-kontrollen i stället för nästa redigeringskontroll i tabbordningen.

  • CFileDialog Klass: Anpassade mallar för CFileDialog klassen kan inte automatiskt portas till Windows Vista. De är fortfarande användbara, men kommer inte att ha ytterligare funktioner eller utseenden som Windows Vista-formatdialogrutor.

  • CWnd Klass och CFrameWnd klass: Metoden CWnd::GetMenuBarInfo har tagits bort.

    Metoden CFrameWnd::GetMenuBarInfo är nu en icke-virtuell metod. Mer information finns i Funktionen GetMenuBarInfo i Windows SDK.

  • MFC ISAPI-stöd: MFC stöder inte längre att skapa program med Internet Server Application Programming Interface (ISAPI). Om du vill skapa ett ISAPI-program anropar du ISAPI-tilläggen direkt.

  • Inaktuella ANSI-API:er: ANSI-versionerna av flera MFC-metoder är inaktuella. Använd Unicode-versionerna av dessa metoder i dina framtida program. Mer information finns i Build Requirements for Windows Vista Common Controls.

Störande ändringar i Visual Studio 2005

CRT

  • Många funktioner har blivit inaktuella. Se Inaktuella CRT-funktioner.

  • Många funktioner verifierar nu sina parametrar och stoppar körningen om de får ogiltiga parametrar. Den här verifieringen kan bryta kod som skickar ogiltiga parametrar och förlitar sig på att funktionen ignorerar dem eller bara returnerar en felkod. Se Parameterverifiering.

  • Filbeskrivningsvärdet -2 används nu för att ange att stdout och stderr inte är tillgängliga för utdata, till exempel i ett Windows-program som inte har något konsolfönster. Det tidigare värdet som användes var -1. Mer information finns i _fileno.

  • De enkeltrådade CRT-biblioteken (libc.lib och libcd.lib) har tagits bort. Använd CRT-bibliotek med flera trådar. Kompilatorflaggan /ML stöds inte längre. Icke-låsningsversioner av vissa funktioner har lagts till i fall där prestandaskillnaden mellan den flertrådade koden och den enkeltrådade koden kan vara betydande.

  • Överlagringen av pow, double pow(int, int) togs bort för att bättre överensstämma med standarden.

  • Den %n formatspecificeraren stöds inte längre som standard i någon av funktionerna i printf-serien eftersom den är osäker. Om %n påträffas är standardbeteendet att anropa den ogiltiga parameterhanteraren. Om du vill aktivera stöd för %n använder du _set_printf_count_output (se _get_printf_count_outputäven ).

  • sprintf skriver nu ut det negativa tecknet på en signerad nolla.

  • swprintf har ändrats för att överensstämma med standarden. det kräver nu en storleksparameter. Formatet swprintf utan en storleksparameter har föråldrats.

  • _set_security_error_handler har tagits bort. Ta bort alla anrop till den funktionen. standardhanteraren är ett mycket säkrare sätt att hantera säkerhetsfel.

  • time_t är nu ett 64-bitarsvärde (om inte _USE_32BIT_TIME_T har definierats).

  • _spawn-, _wspawn-funktionerna lämnar nu errno orörda vid framgång, i enlighet med C-standarden.

  • RTC använder nu breda tecken som standard.

  • Stödfunktionerna för ordstöd för flyttalskontroller har blivit inaktuella för program som kompilerats med /CLR eller /CLR:PURE. De berörda funktionerna är _clear87, _clearfp, _control87, _controlfp, _fpreset, , _status87. _statusfp Du kan inaktivera utfasningsvarningen genom att definiera _CRT_MANAGED_FP_NO_DEPRECATE, men användningen av dessa funktioner i hanterad kod är oförutsägbar och stöds inte.

  • Vissa funktioner returnerar nu const-pekare. Det gamla icke-konstanta beteendet kan återställas genom att definiera _CONST_RETURN. De berörda funktionerna är

    • memchr, wmemchr

    • strchr, wcschr, _mbschr, _mbschr_l

    • strpbrk, wcspbrk, _mbspbrk, _mbspbrk_l

    • strrchr, wcsrchr, _mbsrchr, _mbsrchr_l

    • strstr, wcsstr, _mbsstr, _mbsstr_l

  • När du länkar med Setargv.obj eller Wsetargv.obj går det inte längre att undertrycka expansionen av ett jokertecken på kommandoraden genom att sätta det inom dubbla citattecken. Mer information finns i Utökning av jokerteckenargument.

Standardbibliotek (2005)

  • Undantagsklassen <exception> (som finns i rubriken) har flyttats till std namnområdet. I tidigare versioner fanns den här klassen i det globala namnområdet. Om du vill lösa eventuella fel som anger att undantagsklassen inte kan hittas, lägger du till följande using-sats i din kod: using namespace std;

  • När du anropar valarray::resize()försvinner innehållet i valarray och ersätts med standardvärden. resize()-metoden är avsedd att återinitiera valarray snarare än att utöka den dynamiskt som en vektor.

  • Felsöka iteratorer: Program som skapats med en felsökningsversion av C-Runtime-biblioteket och som använder iteratorer felaktigt kan börja se anspråk vid körning. Om du vill inaktivera dessa kontroller måste du definiera _HAS_ITERATOR_DEBUGGING (ersatt av _ITERATOR_DEBUG_LEVEL efter Visual Studio 2010) till 0. Mer information finns i Felsökningssupport för Iterator

Visual C++ .NET 2003 Kompatibilitetsändringar

Kompilator

  • Avslutande parenteser krävs nu för det definierade förprocessordirektivet (C2004).

  • Explicita specialiseringar hittar inte längre mallparametrar från den primära mallen (kompilatorfel C2146).

  • En skyddad medlem (n) kan endast nås via en medlemsfunktion i en klass (B) som ärver från klassen (A) som den (n) är medlem i (kompilatorfel C2247).

  • Förbättrade hjälpmedelskontroller i kompilatorn identifierar nu otillgängliga basklasser (kompilatorfel C2248).

  • Ett undantag kan inte fångas om destruktorn och/eller kopieringskonstruktorn är otillgänglig (C2316).

  • Standardargument för pekare till funktioner som inte längre tillåts (kompilatorfel C2383).

  • En statisk datamedlem kan inte initieras via härledd klass (kompilatorfel C2477).

  • Initieringen av en typedef tillåts inte av standarden och genererar nu ett kompilatorfel (kompilatorfel C2513).

  • bool är nu en korrekt typ (kompilatorfel C2632).

  • En UDC kan nu skapa tvetydighet med överlagrade operatorer (C2666).

  • Fler uttryck anses nu vara giltiga null-pekarkonstanter (kompilatorfel C2668).

  • mallen<> krävs nu på platser där kompilatorn tidigare skulle antyda det (kompilatorfel C2768).

  • Den explicita specialiseringen av en medlemsfunktion utanför klassen är inte giltig om funktionen redan uttryckligen har specialiserats via en mallklassspecialisering (kompilatorfel C2910).

  • Parametrar för icke-typmallar med flyttal tillåts inte längre (kompilatorfel C2993).

  • Klassmallar tillåts inte som malltypsargument (C3206).

  • Vänfunktionsnamn introduceras inte längre i innehållande namnområde (kompilatorfel C3767).

  • Kompilatorn accepterar inte längre extra kommatecken i ett makro (C4002).

  • Ett objekt av POD-typ som skapats med en initierare av typen () kommer att standardinitieras (C4345).

  • typename krävs nu om ett beroende namn ska behandlas som en typ (kompilatorvarning (nivå 1) C4346).

  • Funktioner som felaktigt betraktades som mallspecialiseringar anses inte längre vara det (C4347).

  • Statiska datamedlemmar kan inte initieras via härledd klass (C4356).

  • En specialisering av klassmallar måste definieras innan den används i en returtyp (kompilatorvarning (nivå 3) C4686).

  • Kompilatorn rapporterar nu oåtkomlig kod (C4702).

Se även

Nyheter för Visual C++ i Visual Studio