Share via


Wijzigingsgeschiedenis van Microsoft C/C++ 2003 - 2015

In dit artikel worden alle belangrijke wijzigingen van Visual Studio 2015 beschreven die teruggaan naar Visual Studio 2003, en in dit artikel worden de termen 'nieuw gedrag' of 'nu' verwezen naar Visual Studio 2015 en hoger. De termen 'oud gedrag' en 'voor' verwijzen naar Visual Studio 2013 en eerdere versies.

Voor informatie over de nieuwste versie van Visual Studio, zie wat er nieuw is voor C++ in Visual Studio en verbeteringen in de C++-naleving in Visual Studio.

Opmerking

Er zijn geen brekende wijzigingen tussen Visual Studio 2015 en Visual Studio 2017.

Wanneer u een upgrade uitvoert naar een nieuwe versie van Visual Studio, kunnen er compilatie- en/of runtimefouten optreden in code die eerder is gecompileerd en correct is uitgevoerd. Wijzigingen in de nieuwe versie die dergelijke problemen veroorzaken, worden belangrijke wijzigingen genoemd en zijn doorgaans vereist door wijzigingen in de C++-taalstandaard, functiehandtekeningen of de indeling van objecten in het geheugen.

Om runtimefouten te voorkomen die moeilijk te detecteren en diagnosticeren zijn, raden we u aan nooit statisch te koppelen aan binaire bestanden die zijn gecompileerd met behulp van een andere versie van de compiler. Wanneer u een EXE- of DLL-project bijwerkt, moet u ook de bibliotheken upgraden waarnaar het is gekoppeld. Geef de typen CRT (C Runtime) of C++ Standard Library (C++ Standard Library) niet door tussen binaire bestanden, inclusief DLL's, gecompileerd met behulp van verschillende versies van de compiler. Voor meer informatie, zie Potentiële fouten bij het doorgeven van CRT-objecten over DLL-grenzen.

U moet nooit code schrijven die afhankelijk is van een bepaalde indeling voor een object dat geen COM-interface of een POD-object is. Als u een dergelijke code schrijft, moet u ervoor zorgen dat deze werkt nadat u een upgrade hebt uitgevoerd. Zie Portabiliteit bij ABI-grenzen voor meer informatie.

Daarnaast kunnen doorlopende verbeteringen in de naleving van de compiler soms veranderen hoe de compiler uw bestaande broncode begrijpt. U kunt bijvoorbeeld nieuwe of andere fouten vinden tijdens uw build, of zelfs gedragsverschillen in code die eerder zijn gebouwd en correct lijken te worden uitgevoerd. Hoewel deze verbeteringen geen belangrijke wijzigingen zijn, zoals de wijzigingen die in dit document worden besproken, moet u mogelijk wijzigingen aanbrengen in uw broncode om deze problemen op te lossen:

Wijzigingen in overeenstemming met Visual Studio 2015

C Runtime Library (CRT)

Algemene Wijzigingen

  • Geherstructureerde binaire bestanden

    De CRT-bibliotheek is geherstructureerd in twee verschillende binaire bestanden: een Universal CRT (ucrtbase), die de meeste standaardfunctionaliteit bevat en een VC Runtime-bibliotheek (vcruntime). De vcruntime-bibliotheek bevat de compiler-gerelateerde functionaliteit, zoals het verwerken van uitzonderingen en intrinsieken. Als u de standaardprojectinstellingen gebruikt, heeft deze wijziging geen invloed op u omdat de linker automatisch gebruikmaakt van de nieuwe standaardbibliotheken. Als u de eigenschap Linker van het project alle standaardbibliotheken negeren op Ja hebt ingesteld of als u de /NODEFAULTLIB linkeroptie op de opdrachtregel gebruikt, moet u de lijst met bibliotheken (in de eigenschap Aanvullende afhankelijkheden ) bijwerken om de nieuwe, geherstructureerde bibliotheken op te nemen. Vervang de oude CRT-bibliotheek (libcmt.lib, libcmtd.lib, msvcrt.lib, msvcrtd.lib) door de equivalente gerefactoreerde bibliotheken. Voor elk van de twee herstructureringsbibliotheken zijn er statische (.lib) en dynamische (.dll) versies en release (zonder achtervoegsel) en foutopsporingsversies (met het achtervoegsel d). De dynamische versies hebben een importbibliotheek waarmee u een koppeling maakt. De twee geherstructureerde bibliotheken zijn Universal CRT, specifiek ucrtbase.dll of ucrtbase.lib, ucrtbased.dll of ucrtbased.lib, en de VC-runtimebibliotheek, libvcruntime.libvcruntimeversie.dll, libvcruntimed.lib en vcruntimedversie.dll. De versie in Visual Studio 2015 en Visual Studio 2017 is 140. Zie CRT-Bibliotheekfuncties.

<locale.h>

  • localeconv

    De localeconv functie die is gedeclareerd in locale.h, werkt nu correct wanneer landinstellingen per thread zijn ingeschakeld. In eerdere versies van de bibliotheek retourneert deze functie de lconv gegevens voor de globale landinstelling, niet de landinstelling van de thread.

    Als u landinstellingen per thread gebruikt, moet u het gebruik van localeconv controleren. Als uw code ervan uitgaat dat de lconv geretourneerde gegevens voor de globale landinstelling zijn, moet u deze corrigeren.

<math.h>

  • C++ overbelasting van wiskundige bibliotheekfuncties

    In eerdere versies definieerde <math.h> enkele, maar niet alle, van de C++-overloads voor de wiskundige bibliotheekfuncties. De rest van de overbelastingen zat in de <cmath> koptekst. Code waarin alleen <math.h> is opgenomen, kan problemen hebben met de oplossing voor functie-overbelasting. Nu zijn de C++ overbelastingen verwijderd uit <math.h> en alleen gevonden in <cmath>.

    Als u fouten wilt oplossen, kunt u <cmath> gebruiken om de declaraties van de functies die uit <math.h> zijn verwijderd op te halen. Deze functies zijn verplaatst:

    • double abs(double) en 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 en long double versies van functies voor drijvende-komma 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, en trunc

    Als u code hebt die gebruikmaakt van abs met een drijvende-komma-type dat alleen de <math.h> header bevat, zijn de drijvende-komma-versies niet meer beschikbaar. De aanroep wordt nu omgezet in abs(int), zelfs met een kommagetalarugment, wat de fout veroorzaakt.

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

    De oplossing voor deze waarschuwing is om de aanroep naar abs te vervangen door een zwevendekommaversie van abs, zoals fabs voor een dubbel argument of fabsf voor een floatargument, of inclusief de <cmath> header en abs te blijven gebruiken.

  • Conformheid van drijvende komma

    Er zijn veel wijzigingen aangebracht in de wiskundige bibliotheek om de conformiteit met de specificaties van de IEEE-754 en C11 bijlage F te verbeteren met betrekking tot invoer in speciale gevallen, zoals NaN's en infinities. Stille NaN-invoer, die vaak als fouten in eerdere versies van de bibliotheek zijn behandeld, worden bijvoorbeeld niet meer behandeld als fouten. Zie IEEE 754 Standard en bijlage F van de C11-standaard.

    Deze wijzigingen veroorzaken geen compilatiefouten, maar kunnen ervoor zorgen dat programma's zich anders en correcter gedragen volgens de standaard.

  • FLT_ROUNDS

    In Visual Studio 2013 is de FLT_ROUNDS macro uitgebreid naar een constante expressie, wat onjuist was omdat de afrondingsmodus tijdens runtime kan worden geconfigureerd, bijvoorbeeld door fesetround aan te roepen. De FLT_ROUNDS macro is nu dynamisch en weerspiegelt de huidige afrondingsmodus correct.

<new> en <new.h>

  • new en delete

    In eerdere versies van de bibliotheek zijn de door de implementatie gedefinieerde operator nieuwe en verwijderfuncties geëxporteerd uit het DLL-bestand van de runtimebibliotheek (bijvoorbeeld msvcr120.dll). Deze operatorfuncties zijn nu altijd statisch gekoppeld aan uw binaire bestanden, zelfs wanneer u de DLL's van de runtimebibliotheek gebruikt.

    Dit is geen belangrijke wijziging voor systeemeigen of gemengde code (/clr), maar voor code die is gecompileerd als /clr:pure, kan deze wijziging ertoe leiden dat uw code niet kan worden gecompileerd. Als u code compileert als /clr:pure, moet u mogelijk #include <new> of #include <new.h> toevoegen om buildfouten te omzeilen vanwege deze wijziging. De/clr:pure optie is afgeschaft in Visual Studio 2015 en wordt niet ondersteund in Visual Studio 2017. Code die 'puur' moet zijn, moet worden overgezet naar C#.

<process.h>

  • _beginthread en _beginthreadex

    De _beginthread en _beginthreadex functies bevatten nu een verwijzing naar de module waarin de threadprocedure is gedefinieerd voor de duur van de thread. Dit helpt ervoor te zorgen dat modules niet worden uitgeladen totdat een thread is voltooid.

<stdarg.h>

  • va_start en verwijzingstypen

    Bij het compileren van C++-code controleert va_start nu tijdens het compileren dat het doorgegeven argument niet van een referentietype is. Verwijzingstypeargumenten zijn verboden volgens de C++-standaard.

<stdio.h> en <conio.h>

  • De functiesfamilie printf en scanf zijn nu inline gedefinieerd.

    De definities van alle printf functies en scanf functies zijn inline verplaatst naar <stdio.h>, <conio.h>en andere CRT-headers. Deze belangrijke wijziging leidt tot een linkerfout (LNK2019, niet-opgelost extern symbool) voor alle programma's die deze functies lokaal hebben gedeclareerd zonder de juiste CRT-headers op te geven. Indien mogelijk moet u de code bijwerken om de CRT-headers (d.w.w.v. toevoegen #include <stdio.h>) en de inlinefuncties op te nemen, maar als u de code niet wilt wijzigen om deze headerbestanden op te nemen, is een alternatieve oplossing om toe te voegen legacy_stdio_definitions.lib aan uw linkerinvoer.

    Als u deze bibliotheek wilt toevoegen aan uw linkerinvoer in de IDE, opent u het contextmenu voor het projectknooppunt, kiest u Eigenschappen en kiest u vervolgens in het dialoogvenster Projecteigenschappen , kiest u Linker en bewerkt u de Linker-invoer om toe te voegen legacy_stdio_definitions.lib aan de door puntkomma's gescheiden lijst.

    Als uw project is gekoppeld aan statische bibliotheken die zijn gecompileerd met een versie van Visual Studio ouder dan 2015, kan de linker een onopgeloste extern symbool rapporteren. Deze fouten kunnen verwijzen naar interne definities voor _iob, _iob_funcof gerelateerde importbewerkingen voor bepaalde <stdio.h> functies in de vorm van imp*. Microsoft raadt u aan om alle statische bibliotheken opnieuw te compileren met de nieuwste versie van de C++-compiler en -bibliotheken wanneer u een project bijwerkt. Als de bibliotheek een bibliotheek van derden is waarvoor de bron niet beschikbaar is, moet u een bijgewerkt binair bestand van de derde partij aanvragen of uw gebruik van die bibliotheek inkapselen in een afzonderlijk DLL-bestand dat u compileert met de oudere versie van de compiler en bibliotheken.

    Waarschuwing

    Als u een koppeling met Windows SDK 8.1 of eerder gebruikt, kunnen deze onopgeloste fouten met externe symbolen optreden. In dat geval moet u de fout oplossen door legacy_stdio_definitions.lib toe te voegen aan de linkerinvoer zoals eerder is beschreven.

    Als u onopgeloste symboolfouten wilt oplossen, kunt u proberen dumpbin.exe de symbolen te onderzoeken die zijn gedefinieerd in een binair bestand. Probeer de volgende opdrachtregel om symbolen weer te geven die zijn gedefinieerd in een bibliotheek.

    dumpbin.exe /LINKERMEMBER somelibrary.lib
    
  • gets en _getws

    De gets- en _getws-functies zijn verwijderd. De functie Gets is verwijderd uit de C Standard-bibliotheek in C11 omdat deze niet veilig kan worden gebruikt. De _getws-functie was een Microsoft-extensie die gelijk was aan gets, maar voor wide strings. Als alternatief voor deze functies kunt u overwegen om fgets, fgetws, gets_s en _getws_s te gebruiken.

  • _cgets en _cgetws

    De functies _cgets en _cgetws zijn verwijderd. Als alternatief voor deze functies kunt u het gebruik van _cgets_s en _cgetws_s overwegen.

  • Oneindigheid en NaN-opmaak

    In eerdere versies worden infinities en NaN's opgemaakt met behulp van een set MSVC-specifieke sentinel-tekenreeksen.

    • Oneindigheid: 1.#INF

    • Stille NaN: 1.#QNAN

    • Signalerende NaN: 1.#SNAN

    • Onbepaalde NaN: 1.#IND

    Een van deze indelingen kan zijn voorafgegaan door een teken en is mogelijk enigszins anders opgemaakt, afhankelijk van de breedte en precisie van het veld (soms met ongebruikelijke effecten wordt bijvoorbeeld printf("%.2f\n", INFINITY) 1,#J afgedrukt omdat de #INF 'afgerond' wordt op een precisie van 2 cijfers). In C99 zijn nieuwe vereisten geïntroduceerd voor de indeling van infiniteiten en NaN's. De MSVC-implementatie voldoet nu aan deze vereisten. De nieuwe tekenreeksen zijn als volgt:

    • Oneindigheid: inf

    • Stille NaN: nan

    • Signalering NaN: nan(snan)

    • Onbepaalde NaN: nan(ind)

    Elk van deze kan worden voorafgegaan door een teken. Als een hoofdletternotatieaanduiding wordt gebruikt (%F in plaats van %f), worden de tekenreeksen afgedrukt in hoofdletters (INF in plaats van inf), zoals vereist.

    De scanf-functies zijn gewijzigd om deze nieuwe tekenreeksen te parseren, zodat deze tekenreeksen nu via printf en scanf heen en weer kunnen worden gestuurd.

  • Opmaak en parsering van drijvende komma

    Om de juistheid te verbeteren, zijn er nieuwe algoritmen geïntroduceerd voor het formatteren en parsen van drijvende komma-getallen. Deze wijziging is van invloed op de printf- en scanf-families van functies en functies zoals strtod.

    De oude opmaakalgoritmen genereren slechts een beperkt aantal cijfers en vullen vervolgens de resterende decimalen met nul. Ze konden meestal tekenreeksen genereren die terug te leiden waren naar de oorspronkelijke drijvende-kommawaarde, maar die niet ideaal waren als u de exacte waarde (of de dichtstbijzijnde decimale representatie daarvan) wilde. De nieuwe opmaakalgoritmen genereren zoveel cijfers als nodig zijn om de waarde weer te geven (of om de opgegeven precisie te vullen). Als voorbeeld van de verbetering; houd rekening met de resultaten bij het afdrukken van een grote kracht van twee:

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

    Oude uitvoer:

    1208925819614629200000000
    

    Nieuwe uitvoer:

    1208925819614629174706176
    

    De oude parseeralgoritmen beschouwen slechts 17 significante cijfers uit de invoertekenreeks en zouden de rest van de cijfers negeren. Deze benadering is voldoende om een nauwe benadering te genereren van de waarde die wordt vertegenwoordigd door de tekenreeks en het resultaat is meestal zeer dicht bij het correct afgeronde resultaat. De nieuwe implementatie beschouwt alle huidige cijfers en produceert het correct afgeronde resultaat voor alle invoerwaarden (maximaal 768 cijfers lang). Bovendien houden deze functies nu rekening met de afrondingsmodus (instelbaar via fesetround). Dit is mogelijk een belangrijke gedragsverandering, aangezien deze functies wellicht verschillende resultaten kunnen opleveren. De nieuwe resultaten zijn altijd correcter dan de oude resultaten.

  • Hexadecimale en oneindigheid/NaN drijvende-komma parseren

    De algoritmen voor het parseren van drijvende komma's parseren nu hexadecimale drijvendekommatekenreeksen (zoals de tekenreeksen die zijn gegenereerd door de %a en %A printf-indeling) en alle oneindige en NaN-tekenreeksen die door de printf functies worden gegenereerd, zoals hierboven beschreven.

  • %A en %a nulopvulling

    De %a en %A opmaakspecifieringen formatteren een drijvend kommagetal als een hexadecimale mantissa en binaire exponent. In eerdere versies zouden de printf functies ten onrechte tekenreeksen met nul pad bevatten. Bijvoorbeeld, printf("%07.0a\n", 1.0) zou 00x1p+0 afdrukken, terwijl het 0x01p+0 zou moeten afdrukken. Deze fout is opgelost.

  • %A en %a precisie

    De standaardprecisie van de %A en %a notatieaanduidingen was 6 in eerdere versies van de bibliotheek. De standaardprecisie is nu 13 voor overeenstemming met de C-standaard.

    Dit is een runtimegedragswijziging in de uitvoer van een functie die gebruikmaakt van een notatietekenreeks met %A of %a. In het oude gedrag kan de uitvoer met behulp van de %A-aanduiding '1.1A2B3Cp+111' zijn. De uitvoer voor dezelfde waarde is nu '1.1A2B3C4D5E6F7p+111'. Als u het oude gedrag wilt ophalen, kunt u de precisie opgeven, bijvoorbeeld %.6A. Zie Precisiespecificatie.

  • %F specificatie

    De %F indeling/conversieaanduiding wordt nu ondersteund. Het is functioneel gelijk aan de %f indelingsaanduiding, behalve dat infiniteiten en NaN's zijn opgemaakt met hoofdletters.

    In eerdere versies werd de implementatie gebruikt om F en N te parseren als lengteaanpassingen. Dit gedrag dateert uit de leeftijd van gesegmenteerde adresruimten: deze lengteaanpassingen werden gebruikt om respectievelijk ver- en bijna-aanwijzers aan te geven, zoals in %Fp of %Ns. Dit gedrag is verwijderd. Als %F wordt aangetroffen, wordt deze nu behandeld als de %F indelingsaanduiding; als %N wordt aangetroffen, wordt deze nu behandeld als een ongeldige parameter.

  • Exponent-opmaak

    De %e en %E notatieaanduidingen maken een drijvende kommanummer op als een decimaal mantissa en exponent. De %g- en %G notatieaanduidingen maken in sommige gevallen ook getallen in deze vorm op. In eerdere versies genereert de CRT altijd tekenreeksen met exponenten met drie cijfers. Zou bijvoorbeeld printf("%e\n", 1.0) 1.000000e+000 afdrukken, wat onjuist was. C vereist dat als de exponent slechts één of twee cijfers kan worden weergegeven, slechts twee cijfers moeten worden afgedrukt.

    In Visual Studio 2005 is een algemene conformance-switch toegevoegd: _set_output_format. Een programma kan deze functie aanroepen met het argument _TWO_DIGIT_EXPONENT, om het afdrukken van de conforme exponent mogelijk te maken. Het standaardgedrag is gewijzigd in de standaardconforme exponent-afdrukmodus.

  • Tekenreeksvalidatie opmaken

    In eerdere versies accepteren de printf en scanf functies op de achtergrond veel ongeldige notatietekenreeksen, soms met ongebruikelijke effecten. %hlhlhld wordt bijvoorbeeld behandeld als %d. Alle ongeldige notatietekenreeksen worden nu behandeld als ongeldige parameters.

  • validatie van tekenreeks in de fopen-modus

    In eerdere versies heeft de fopen familie van functies op de achtergrond enkele ongeldige modustekenreeksen geaccepteerd, zoals r+b+. Ongeldige modustekenreeksen worden nu gedetecteerd en behandeld als ongeldige parameters.

  • _O_U8TEXT modus

    De functie _setmode rapporteert nu correct de modus voor streams die zijn geopend in de _O_U8TEXT-modus. In eerdere versies van de bibliotheek zou het dergelijke streams rapporteren als geopend in _O_WTEXT.

    Dit is een belangrijke wijziging als uw code de _O_WTEXT-modus interpreteert voor streams waarbij de codering UTF-8 is. Als uw toepassing geen ondersteuning biedt voor UTF_8, kunt u overwegen om ondersteuning toe te voegen voor deze steeds vaker voorkomende codering.

  • snprintf en vsnprintf

    De functies snprintf en vsnprintf zijn nu geïmplementeerd. Oudere code bevat vaak definities van macroversies van deze functies omdat ze niet zijn geïmplementeerd door de CRT-bibliotheek, maar ze zijn niet meer nodig in nieuwere versies. Als snprintf of vsnprintf als een macro is gedefinieerd voordat <stdio.h> wordt opgenomen, mislukt de compilatie nu met een foutmelding die aangeeft waar de macro is gedefinieerd.

    Normaal gesproken is het oplossen van dit probleem het verwijderen van declaraties van snprintf of vsnprintf in gebruikerscode.

  • tmpnam genereert bruikbare bestandsnamen

    In eerdere versies genereerden de tmpnam en tmpnam_s functies bestandsnamen in de rootdirectory van het station (zoals \sd3c.). Deze functies genereren nu bruikbare bestandsnaampaden in een tijdelijke map.

  • BESTANDScapsulatie

    In eerdere versies is het volledige FILE-type openbaar gedefinieerd in <stdio.h>, dus het was mogelijk dat gebruikerscode toegang heeft tot een BESTAND en de interne structuren ervan kon wijzigen. De bibliotheek is gewijzigd om implementatiedetails te verbergen. Als onderdeel van deze wijziging is BESTAND, zoals gedefinieerd in <stdio.h>, nu een niet-transparant type en zijn de leden niet toegankelijk van buiten de CRT zelf.

  • _outp en _inp

    De functies _outp, _outpw, _outpd, _inp, _inpw en _inpd zijn verwijderd.

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

  • strtof en wcstof

    De functies strtof en wcstof slaagden er niet in om errno op ERANGE in te stellen wanneer de waarde niet als float kon worden weergegeven. Deze fout was specifiek voor deze twee functies; de strtod, wcstod, strtold, en wcstold functies werden niet beïnvloed. Dit probleem is opgelost en is een verandering die runtime-onderbrekingen veroorzaakt.

  • Uitgelijnde toewijzingsfuncties

    In eerdere versies zouden de uitgelijnde toewijzingsfuncties (_aligned_malloc, _aligned_offset_mallocenzovoort) op de achtergrond aanvragen voor een blok accepteren met een uitlijning van 0. De gevraagde uitlijning moet een macht van twee zijn, wat niet waar is voor nul. Een aangevraagde uitlijning van 0 wordt nu behandeld als een ongeldige parameter. Dit probleem is opgelost en is een verandering die runtime-onderbrekingen veroorzaakt.

  • Heap-functies

    De _heapadd, _heapseten _heapused functies zijn verwijderd. Deze functies zijn niet-functioneel sinds de CRT is bijgewerkt om de Windows-heap te gebruiken.

  • smallheap

    De smallheap koppelingsoptie is verwijderd. Zie Koppelingsopties.

  • _Stat

    De _stat-functies maken gebruik van CreateFile in Visual Studio 2015, in plaats van FindFirstFile zoals in Visual Studio 2013 en eerder. Dit betekent dat _stat op een pad dat eindigt op een slash slaagt als het pad verwijst naar een map, in tegenstelling tot voordat de functie een fout zou veroorzaken met errno ingesteld op ENOENT.

<string.h>

  • wcstok

    De handtekening van de wcstok functie is gewijzigd zodat deze overeenkomt met wat vereist is voor de C Standard. In eerdere versies van de bibliotheek was de handtekening van deze functie:

    wchar_t* wcstok(wchar_t*, wchar_t const*)
    

    Er is een interne context per thread gebruikt om de status bij te houden tussen aanroepen, zoals wordt gedaan voor strtok. De functie heeft nu de handtekening wchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**)en vereist dat de aanroeper de context als een derde argument doorgeeft aan de functie.

    Er is een nieuwe _wcstok functie toegevoegd met de oude handtekening om de overdracht te vereenvoudigen. Bij het compileren van C++-code is er ook een inline overload van wcstok die de oude signatuur heeft. Deze overload is als verouderd gemarkeerd. In C-code kunt u define_CRT_NON_CONFORMING_WCSTOK definiëren zodat _wcstok wordt gebruikt in plaats van wcstok.

<time.h>

  • klok

    In eerdere versies is de clock functie geïmplementeerd met behulp van de Windows-API GetSystemTimeAsFileTime. Met deze implementatie was de klokfunctie gevoelig voor de systeemtijd en was dus niet noodzakelijkerwijs monotone. De klokfunctie is heringevoerd aan de hand van QueryPerformanceCounter en is nu monotoon.

  • fstat en _utime

    In eerdere versies verwerken de _stat, fstaten _utime functies de zomertijd onjuist. Vóór Visual Studio 2013 pasten al deze functies de standaardtijd incorrect aan alsof het zomertijd was.

    In Visual Studio 2013 is het probleem opgelost in de _stat functiesfamilie, maar de vergelijkbare problemen in de fstat functies en _utime families van functies zijn niet opgelost. Deze gedeeltelijke oplossing heeft geleid tot problemen vanwege de inconsistentie tussen de functies. De fstat functies en _utime families van functies zijn nu opgelost, dus al deze functies verwerken nu zomertijd correct en consistent.

  • asctime

    In eerdere versies zou de functie asctime dagen met één cijfer aanvullen met een voorloopnul, bijvoorbeeld: Fri Jun 06 08:00:00 2014. De specificatie vereist dat dergelijke dagen worden opgevuld met een spatie aan het begin, zoals in Fri Jun 6 08:00:00 2014. Dit probleem is opgelost.

  • strftime en wcsftime

    De strftime en wcsftime functies ondersteunen nu de %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %uen %V opmaakaanduidingen. Daarnaast worden de E- en O-modifiers geparseerd, maar genegeerd.

    De %c notatieaanduiding is gespecificeerd om een "geschikte datum- en tijdweergave" te geven voor de huidige landinstellingen. In de C-landinstelling moet deze weergave hetzelfde zijn als %a %b %e %T %Y, hetzelfde formulier als wordt geproduceerd door asctime. In eerdere versies werd de %c-notatieaanduiding onjuist gebruikt om tijden te formatteren met een MM/DD/YY HH:MM:SS representatie. Dit probleem is opgelost.

  • timespec en TIME_UTC

    De <time.h> header definieert nu het timespec type en de timespec_get functie van de C11 Standard. Daarnaast is de TIME_UTC macro, voor gebruik met de timespec_get functie, nu gedefinieerd. Deze update is een belangrijke wijziging voor code met een conflicterende definitie voor een van deze id's.

  • CLOCKS_PER_SEC (klokken per seconde)

    De CLOCKS_PER_SEC macro wordt nu uitgebreid naar een geheel getal van het type clock_t, zoals vereist voor de C-taal.

C++ Standaardbibliotheek

Als u nieuwe optimalisaties en foutopsporingscontroles wilt inschakelen, verbreekt de Visual Studio-implementatie van de C++ Standard-bibliotheek opzettelijk binaire compatibiliteit van de ene versie naar de volgende. Wanneer de standaardbibliotheek van C++ wordt gebruikt, kunnen objectbestanden en statische bibliotheken die zijn gecompileerd met verschillende versies, niet worden gecombineerd in één binair bestand (EXE of DLL) en kunnen C++ Standard Library-objecten niet worden doorgegeven tussen binaire bestanden die met verschillende versies worden gecompileerd. Dergelijke menging veroorzaakt linkerfouten vanwege _MSC_VER-mismatches. (_MSC_VER is de macro met de primaire versie van de compiler, bijvoorbeeld 1800 voor Visual Studio 2013.) Met deze controle kan DLL-menging niet worden gedetecteerd en kan geen menging worden gedetecteerd waarbij Visual Studio 2008 of eerder is betrokken.

  • C++ Standaardbibliotheek bevat bestanden

    Er zijn enkele wijzigingen aangebracht in de insluitingsstructuur in de C++ Standard Library-headers. C++ Standaardbibliotheekheaders mogen elkaar op niet-opgegeven manieren opnemen. Over het algemeen moet u uw code schrijven, zodat deze zorgvuldig alle headers bevat die nodig zijn volgens de C++-standaard en niet afhankelijk is van welke C++ Standard Library-headers andere C++ Standard-bibliotheekheaders bevatten. Dit maakt code draagbaar in verschillende versies en platforms. Ten minste twee headerwijzigingen in Visual Studio 2015 zijn van invloed op gebruikerscode. Eerst bevat <string> niet langer <iterator>. Ten tweede declareert <tuple> nu zonder alle std::array op te nemen, waardoor code kan worden verbroken door de volgende combinatie van codeconstructies: uw code heeft een variabele met de naam 'array', en u hebt een using-directive 'using namespace std;', en u voegt een C++ Standard Library-header (zoals <array>) toe die <functional> bevat, die nu <tuple> declareert.

  • steady_clock

    De <chrono> implementatie van steady_clock is veranderd om te voldoen aan de C++-standaardvereisten voor stabielheid en monotoniteit. steady_clock is nu gebaseerd op QueryPerformanceCounter en high_resolution_clock is nu een typedef voor steady_clock. Als gevolg hiervan is Visual Studio steady_clock::time_point nu een typedef voor chrono::time_point<steady_clock>. Dit is echter niet noodzakelijkerwijs het geval voor andere implementaties.

  • allocators en const

    We vereisen nu dat vergelijkingen van allocator voor gelijkheid/ongelijkheid const-argumenten aan beide zijden accepteren. Als uw toewijzingen deze operators als volgt definiëren,

    bool operator==(const MyAlloc& other)
    

    vervolgens moet u ze bijwerken en declareren als const-leden:

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

    De C++-standaard heeft altijd verboden containers van const-elementen (zoals vector<const T> of set<const T>). Visual Studio 2013 en eerder hebben dergelijke containers geaccepteerd. In de huidige versie kunnen dergelijke containers niet worden gecompileerd.

  • std::allocator::dealloceer

    In Visual Studio 2013 en eerder negeerde std::allocator::deallocate(p, n) het argument dat voor n was doorgegeven. De C++-standaard heeft altijd vereist dat n gelijk moet zijn aan de waarde die als eerste argument is doorgegeven aan de aanroep van allocate, die p heeft geretourneerd. In de huidige versie wordt de waarde van n echter geïnspecteerd. Code die argumenten doorgeeft voor n die verschillen van wat de standaard vereist, kan tijdens runtime vastlopen.

  • hash_map en hash_set

    De niet-standaardheaderbestanden <hash_map> en <hash_set> zijn afgeschaft in Visual Studio 2015 en worden verwijderd in een toekomstige release. Gebruik <unordered_map> en <unordered_set> in plaats daarvan.

  • comparators en operator()

    Associatieve containers (de <map>-familie) vereisen nu dat hun comparators functieaanroepen hebben die const oproepbaar zijn. De volgende code in een declaratie van de comparatorklasse kan nu niet worden gecompileerd:

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

    Als u deze fout wilt oplossen, wijzigt u de functiedeclaratie in:

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

    De oude namen voor typeeigenschappen uit een eerdere versie van de C++-conceptstandaard zijn verwijderd. Deze zijn gewijzigd in C++11 en zijn bijgewerkt naar de C++11-waarden in Visual Studio 2015. In de volgende tabel ziet u de oude en nieuwe namen.

    Oude naam Nieuwe naam
    referentie_toevoegen add_lwaarde_referentie
    heeft_standaard_constructor Is standaard constructibel
    heeft_kopie_constructor is_copy_constructible
    beschikt_over_een_verplaatsingsconstructor is_move_constructible
    heeft_nothrow_constructor is_nothrow_default_constructable
    heeft_een_niet-werfbare_standaardconstructor is_nothrow_default_constructable
    heeft_geen_throw_copy is_nothrow_copy_constructible
    has_nothrow_copy_constructor is_nothrow_copy_constructible
    has_nothrow_move_constructor is_nothrow_move_constructible
    heeft_geen_exceptie_toewijzing is_nothrow_copy_assignable
    has_nothrow_copy_assign (gegarandeerd geen excepties bij de copy-assignfunctie) is_nothrow_copy_assignable
    heeft_throw-loze_verplaats_toewijzing is_nothrow_verplaatsbaar_toewijsbaar
    heeft_een_eenvoudige_constructor is_eenvoudig_standaard_constructeerbaar
    heeft_triviale_standaard_constructor is_eenvoudig_standaard_constructeerbaar
    heeft_triviale_kopie is_triviaal_kopie_constructie
    has_trivial_move_constructor is_trivially_move_constructible
    has_triviale_toewijzing is_triviaal_kopieerbaar_toewijzen
    has_triviale_verplaatstoewijzing is_trivially_move_assignable
    heeft_een_triviale_destructor is_trivially_destructible
  • launch::any en launch::sync beleid

    De niet-standaard launch::any en launch::sync beleidsregels zijn verwijderd. Gebruik in plaats daarvan launch::any voor launch:async | launch:deferred. Voor launch::sync, gebruik launch::deferred. Zie Enumeration starten.

MFC en ATL

  • Microsoft Foundation-klassen (MFC)

    is niet langer opgenomen in een 'typische' installatie van Visual Studio vanwege de grote grootte. Als u MFC wilt installeren, kiest u de optie Aangepaste installatie in Visual Studio 2015 setup. Als u Visual Studio 2015 al hebt geïnstalleerd, kunt u MFC installeren door Visual Studio opnieuw in te stellen. Kies de optie Aangepaste installatie en kies vervolgens Microsoft Foundation Classes. U kunt Visual Studio setup uitvoeren vanuit het Configuratieschermprogramma's en onderdelen, of vanaf de installatiemedia.

    Het Herdistribueerbare pakket van Visual C++ bevat nog steeds deze bibliotheek.

Gelijktijdigheidsruntime

  • Opbrengstmacro van Windows.h die conflicteert met gelijktijdigheid::Context::Opbrengst

    De Gelijktijdigheidsruntime heeft eerder #undef gebruikt om de Yield-macro ongedaan te maken en zo conflicten te vermijden tussen de Yield-macro die is gedefinieerd in Windows.h en de concurrency::Context::Yield-functie. Dit #undef is verwijderd en er is een nieuwe niet-conflicterende equivalente API-aanroep gelijktijdigheid:::Context::YieldExecution toegevoegd. Als u conflicten met Yield wilt omzeilen, kunt u de code bijwerken om de YieldExecution functie aan te roepen of de Yield functienaam tussen haakjes op aanroepsites plaatsen, zoals in het volgende voorbeeld:

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

Verbeteringen van compilerconformance in Visual Studio 2015

Bij het upgraden van code uit eerdere versies kunnen er ook compilerfouten optreden die worden veroorzaakt door verbeteringen in de conformiteit die zijn aangebracht in Visual Studio 2015. Deze verbeteringen schenden de binaire compatibiliteit van eerdere versies van Visual Studio niet, maar ze kunnen compilerfouten veroorzaken waar eerder geen fouten werden gegenereerd. Zie Visual C++ Wat is er nieuw 2003 tot en met 2015 voor meer informatie.

In Visual Studio 2015 kunnen doorlopende verbeteringen in de naleving van compileren soms veranderen hoe de compiler uw bestaande broncode begrijpt. Als gevolg hiervan kunt u nieuwe of andere fouten tegenkomen tijdens uw build, of zelfs gedragsverschillen in code die eerder zijn gebouwd en correct lijken te worden uitgevoerd.

Gelukkig hebben deze verschillen weinig of geen invloed op de meeste van uw broncode. Wanneer broncode of andere wijzigingen nodig zijn om deze verschillen aan te pakken, zijn de oplossingen meestal klein en eenvoudig. We hebben veel voorbeelden van eerder acceptabele broncode opgenomen die mogelijk moet worden gewijzigd (vóór) en de oplossingen om ze (na) te corrigeren.

Hoewel deze verschillen van invloed kunnen zijn op uw broncode of andere buildartefacten, hebben ze geen invloed op binaire compatibiliteit tussen updates voor Visual Studio-versies. Een belangrijke wijziging is ernstiger en kan van invloed zijn op binaire compatibiliteit, maar dit soort binaire compatibiliteitseinden vindt alleen plaats tussen primaire versies van Visual Studio, bijvoorbeeld tussen Visual Studio 2013 en Visual Studio 2015. Zie Visual Studio 2015 Conformance-wijzigingen voor informatie over de belangrijke wijzigingen die zijn opgetreden tussen Visual Studio 2013 en Visual Studio 2015.

Nalevingsverbeteringen in Visual Studio 2015

  • /Zc:forScope- optie

    De compileroptie /Zc:forScope- is afgeschaft en wordt verwijderd in een toekomstige release.

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

    Deze optie is meestal gebruikt om niet-standaardcode toe te staan die lusvariabelen gebruikt na het punt waar, volgens de standaard, ze buiten het bereik moeten zijn gegaan. Het was alleen nodig toen u met de /Za optie hebt gecompileerd, omdat zonder /Za, het gebruik van een for-lusvariabele na het einde van de lus altijd is toegestaan. Als u niet belangrijk bent voor de naleving van standaarden (bijvoorbeeld als uw code niet is bedoeld om over te dragen aan andere compilers), kunt u de /Za optie uitschakelen (of de eigenschap Taalextensies uitschakelen op Nee instellen). Als u wel wilt dat u draagbare, standaardenconforme code schrijft, moet u uw code herschrijven zodat deze voldoet aan de standaard door de declaratie van dergelijke variabelen naar een punt buiten de lus te verplaatsen.

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

    De /Zg compileroptie (Functieprototypes genereren) is niet meer beschikbaar. Deze compileroptie is eerder afgeschaft.

  • U kunt geen eenheidstests meer uitvoeren met C++/CLI vanaf de opdrachtregel met mstest.exe. Gebruik in plaats daarvan vstest.console.exe. Zie VSTest.Console.exe opdrachtregelopties.

  • veranderlijk trefwoord

    De mutable aanduiding van de opslagklasse is niet meer toegestaan op plaatsen waar deze eerder zonder fouten is gecompileerd. De compiler geeft nu fout C2071 (illegale opslagklasse). Volgens de standaard kan de mutable aanduiding alleen worden toegepast op namen van klassegegevensleden en kan deze niet worden toegepast op namen die const of statisch zijn gedeclareerd en kunnen ze niet worden toegepast op verwijzingsleden.

    Denk bijvoorbeeld aan de volgende code:

    struct S
    {
        mutable int &r;
    };
    

    Vorige versies van de compiler hebben dit geaccepteerd, maar nu geeft de compiler de volgende fout:

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

    Verwijder het redundante mutable trefwoord om de fout op te lossen.

  • char_16_t en char32_t

    U kunt niet langer char16_t of char32_t als aliassen in een typedef gebruiken, omdat deze typen nu als standaard worden beschouwd. Het was gebruikelijk voor gebruikers en bibliotheekauteurs om char16_t en char32_t respectievelijk als aliassen van uint16_t en uint32_t te definiëren.

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

    Als u de code wilt bijwerken, verwijdert u de typedef declaraties en wijzigt u de naam van andere id's die met deze namen in conflict komen.

  • Niet-typen sjabloonparameters

    Bepaalde code die niet-typesjabloonparameters omvat, wordt nu correct gecontroleerd op typecompatibiliteit wanneer u expliciete sjabloonargumenten opgeeft. De volgende code is bijvoorbeeld gecompileerd zonder fout in eerdere versies van 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>();
    }
    

    De huidige compiler geeft een fout, omdat het parametertype van de sjabloon niet overeenkomt met het sjabloonargument (de parameter is een aanwijzer naar een const-lid, maar de functie f is niet-const):

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

    Als u deze fout in uw code wilt oplossen, moet u ervoor zorgen dat het type sjabloonargument dat u gebruikt overeenkomt met het gedeclareerde type van de sjabloonparameter.

  • __declspec(align)

    De compiler accepteert __declspec(align) niet meer bij functies. Deze constructie is altijd genegeerd, maar er wordt nu een compilerfout gegenereerd.

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

    Als u dit probleem wilt oplossen, verwijdert u __declspec(align) uit de functiedeclaratie. Omdat het geen effect had, verandert het verwijderen niets.

  • afhandeling van uitzonderingen

    Er zijn enkele wijzigingen in de afhandeling van uitzonderingen. Ten eerste moeten uitzonderingsobjecten kopieerbaar of verplaatsbaar zijn. De volgende code die is gecompileerd in Visual Studio 2013, maar wordt niet gecompileerd in Visual Studio 2015:

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

    Het probleem is dat de kopieerconstructor privé is, zodat het object niet kan worden gekopieerd zoals dat normaal gebeurt bij het afhandelen van een uitzondering. Hetzelfde geldt wanneer de kopieerconstructor wordt gedeclareerd explicit.

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

    Als u de code wilt bijwerken, zorg er dan voor dat de kopieerconstructor voor uw uitzonderingsobject public is en niet explicit gemarkeerd is.

    Om een uitzondering op waarde te vangen, moet het uitzonderingsobject ook kopieerbaar zijn. De volgende code die is gecompileerd in Visual Studio 2013, maar wordt niet gecompileerd in Visual Studio 2015:

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

    U kunt dit probleem oplossen door het parametertype voor de catch in een verwijzing te wijzigen.

    catch (D& d)
    {
    }
    
  • Letterlijke tekenreeksen gevolgd door macro's

    De compiler ondersteunt nu door de gebruiker gedefinieerde letterlijke gegevens. Als gevolg hiervan worden letterlijke tekenreeksen gevolgd door macro's zonder tussenliggende witruimte geïnterpreteerd als door de gebruiker gedefinieerde letterlijke gegevens, wat fouten of onverwachte resultaten kan opleveren. In eerdere compilers is bijvoorbeeld de volgende code gecompileerd:

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

    De compiler interpreteerde deze code als een letterlijke tekenreeks 'hallo' gevolgd door een macro, die is uitgebreid naar 'daar', en vervolgens werden de twee letterlijke tekenreeksen samengevoegd tot één. In Visual Studio 2015 interpreteert de compiler deze reeks als een door de gebruiker gedefinieerde letterlijk, maar omdat er geen overeenkomende door de gebruiker gedefinieerde letterlijke _x is, geeft het een fout.

    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?
    

    U kunt dit probleem oplossen door een spatie toe te voegen tussen de letterlijke tekenreeks en de macro.

  • Letterlijke tekenreeksen naast elkaar

    Net als bij het vorige, werden, vanwege gerelateerde wijzigingen in tekenreeksparsering, aangrenzende letterlijke tekenreeksen (letterlijke tekenreeksen breed of smal) zonder witruimte geïnterpreteerd als één samengevoegde tekenreeks in eerdere versies van Visual C++. In Visual Studio 2015 moet u nu witruimte toevoegen tussen de twee tekenreeksen. De volgende code moet bijvoorbeeld worden gewijzigd:

    char * str = "abc""def";
    

    U kunt dit probleem oplossen door een spatie toe te voegen tussen de twee tekenreeksen:

    char * str = "abc" "def";
    
  • Plaatsing nieuw en verwijderen

    Er is een wijziging aangebracht in de delete operator om deze in overeenstemming te brengen met de C++14-standaard. Details van de wijziging van de standaarden vindt u op C++ Size Deallocation. Met de wijzigingen wordt een vorm toegevoegd van de globale delete operator die een grootteparameter gebruikt. De belangrijke wijziging is dat als u eerder een operator delete met dezelfde signatuur gebruikte (om te corresponderen met een plaatsingsoperator 'new'), u een compilerfout ontvangt (C2956, die optreedt op het punt waar de plaatsingsoperator 'new' wordt gebruikt, omdat dat de positie in de code is waar de compiler probeert de bijbehorende operator te identificeren).

    De functie void operator delete(void *, size_t) was een operator voor plaatsings verwijderen die overeenkomt met de nieuwe plaatsingsfunctievoid * operator new(size_t, size_t) in C++11. Met deallocatie van C++14 is deze verwijderfunctie nu een gebruikelijke deallocatiefunctie (globale delete operator). De standaard vereist dat als het gebruik van een nieuwe plaatsing een bijbehorende verwijderfunctie opzoekt en een gebruikelijke deallocatiefunctie vindt, het programma onopgevormd is.

    Stel dat uw code zowel een nieuwe plaatsing als een plaatsings verwijderen definieert:

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

    Het probleem treedt op vanwege de overeenkomst in functiedeclaraties tussen een door u gedefinieerde placement delete operator en de nieuwe globale delete operator. Overweeg of u een ander type kunt gebruiken dan size_t voor placement new en delete operatoren. Het type van de size_ttypedef is afhankelijk van de compiler; het is een typedef voor unsigned int in MSVC. Een goede oplossing is het gebruik van een geïnventariseerd type zoals deze:

    enum class my_type : size_t {};
    

    Wijzig vervolgens de definitie van nieuwe plaatsing en delete gebruik dit type als het tweede argument in plaats van size_t. U moet ook de aanroepen van 'placement new' bijwerken om het nieuwe type door te geven (bijvoorbeeld door static_cast<my_type> te gebruiken om vanuit de integerwaarde te converteren) en de definitie van new en delete om terug te casten naar het integertype. U hoeft hiervoor geen gebruik te maken enum . Een klassetype met een size_t lid werkt ook.

    Een alternatieve oplossing is dat u het gebruik van placement new mogelijk helemaal kunt elimineren. Als uw code gebruikmaakt van plaatsing nieuw om een geheugengroep te implementeren waarbij het plaatsingsargument de grootte is van het object dat wordt toegewezen of verwijderd, is de functie deallocatie mogelijk geschikt om uw eigen aangepaste geheugengroepcode te vervangen en kunt u de plaatsingsfuncties verwijderen en gewoon uw eigen operator met twee argumenten delete gebruiken in plaats van de plaatsingsfuncties.

    Als u de code niet onmiddellijk wilt bijwerken, kunt u teruggaan naar het oude gedrag met behulp van de compileroptie /Zc:sizedDealloc-. Als u deze optie gebruikt, bestaan de verwijderfuncties met twee argumenten niet en veroorzaken ze geen conflict met de operator voor het verwijderen van plaatsingen .

  • Union-gegevensleden

    Lidgegevens van unions kunnen geen referentietypen meer hebben. De volgende code is gecompileerd in Visual Studio 2013, maar produceert een fout in Visual Studio 2015.

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

    De voorgaande code produceert de volgende fouten:

    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
    

    Als u dit probleem wilt oplossen, wijzigt u de verwijzingstypen in een aanwijzer of een waarde. Als u het type wijzigt in een aanwijzer, moeten wijzigingen worden aangebracht in de code die gebruikmaakt van het samenvoegveld. Als u de code wijzigt in een waarde, worden de gegevens die zijn opgeslagen in de samenvoeging gewijzigd, wat van invloed is op andere velden, omdat velden in samenvoegtypen hetzelfde geheugen delen. Afhankelijk van de grootte van de waarde kan deze ook de grootte van de samenvoeging wijzigen.

  • Anonieme vakbonden zijn nu meer conform de standaard. Vorige versies van de compiler hebben een expliciete constructor en destructor gegenereerd voor anonieme samenvoegingen. Deze door compiler gegenereerde functies worden verwijderd in Visual Studio 2015.

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

    Met de voorgaande code wordt de volgende fout gegenereerd in Visual Studio 2015:

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

    U kunt dit probleem oplossen door uw eigen definities van de constructor en/of destructor op te geven.

    struct S
    {
        // Provide a default constructor by adding an empty function body.
        S() {}
    };
    
    union
    {
        struct
        {
            S s;
        };
    } u;
    
  • Samenvoegingen met anonieme structs

    Om aan de standaard te voldoen, is het runtimegedrag gewijzigd voor leden van anonieme structuren in vakbonden. De constructor voor anonieme structuurleden in een samenvoeging wordt niet langer impliciet aangeroepen wanneer een dergelijke samenvoeging wordt gemaakt. Ook wordt de destructor voor anonieme structuurleden in een unie niet langer impliciet aangeroepen wanneer de unie buiten zijn bereik komt. Houd rekening met de volgende code, waarin een union U een anonieme structuur bevat die een benoemde lidstructuur S bevat die een destructor heeft.

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

    In Visual Studio 2013 wordt de constructor voor S aangeroepen wanneer de samenvoeging wordt gemaakt en wordt de destructor voor S aangeroepen wanneer de stack voor functie f wordt opgeschoond. Maar in Visual Studio 2015 worden de constructor en destructor niet aangeroepen. De compiler geeft een waarschuwing over dit gedrag.

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

    Als u het oorspronkelijke gedrag wilt herstellen, geeft u de anonieme structuur een naam. Het runtimegedrag van niet-anonieme structuren is hetzelfde, ongeacht de compilerversie.

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

    U kunt ook proberen de constructor en destructorcode naar nieuwe functies te verplaatsen en aanroepen aan deze functies toe te voegen vanuit de constructor en destructor voor de samenvoeging.

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

    Er zijn wijzigingen aangebracht in de naamresolutie voor sjablonen. Wanneer u in C++ kandidaten voor de oplossing van een naam in overweging neemt, kan het gebeuren dat een of meer namen die worden overwogen als mogelijke overeenkomsten een ongeldige sjablooninstantiëring opleveren. Deze ongeldige instantiëringen veroorzaken normaal gesproken geen compilerfouten, een principe dat bekend staat als SFINAE (vervangingsfout is geen fout).

    Als SFINAE vereist dat de compiler de specialisatie van een klassesjabloon instantiëren, zijn eventuele fouten die tijdens dit proces optreden compilerfouten. In eerdere versies negeert de compiler dergelijke fouten. Denk bijvoorbeeld aan de volgende code:

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

    Als u compileert met de huidige compiler, krijgt u de volgende fout:

    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
    ]
    

    Dit komt doordat op het punt van de eerste aanroep van de is_base_of de klasse D nog niet is gedefinieerd.

    In dit geval is de oplossing om dergelijke typeeigenschappen pas te gebruiken als de klasse is gedefinieerd. Als u de definities van B en D naar het begin van het codebestand verplaatst, wordt de fout opgelost. Als de definities zich in headerbestanden bevinden, controleert u de volgorde van de insluitingsinstructies voor de headerbestanden om ervoor te zorgen dat eventuele klassedefinities worden gecompileerd voordat de problematische sjablonen worden gebruikt.

  • Constructors kopiëren

    In zowel Visual Studio 2013 als Visual Studio 2015 genereert de compiler een kopieerconstructor voor een klasse als die klasse een door de gebruiker gedefinieerde verplaatsingsconstructor heeft, maar geen door de gebruiker gedefinieerde kopieerconstructor. In Dev14 is deze impliciet gegenereerde kopieerconstructor ook gemarkeerd als '= delete'.

  • main, gedeclareerd als extern "C", vereist nu een retourtype.

    De volgende code produceert nu C4430.

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

    Als u de fout wilt oplossen, voegt u het retourtype toe:

    extern "C" int __cdecl main(){} // OK
    
  • typename is niet toegestaan in een initialisatiefunctie voor leden

    De volgende code produceert nu C2059:

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

    Om de fout te herstellen, verwijdert u typename uit de initialisatiefunctie.

    S1() : T::type() // OK
    ...
    
  • De opslagklasse voor expliciete specialisaties wordt genegeerd.

    In de volgende code wordt de statische opslagklasseaanduiding genegeerd

    template <typename T>
    void myfunc(T h)
    {
    }
    
    template<>
    static void myfunc(double h) // static is ignored
    {
    }
    
  • Een constante die in een static_assert in een klassesjabloon wordt gebruikt, mislukt altijd.

    De volgende code zorgt ervoor dat de static_assert code altijd mislukt:

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

    Om dit probleem te omzeilen, wikkel de waarde in een 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
    
  • Regels die worden afgedwongen voor doorstuurdeclaraties. (Alleen van toepassing op C.)

    De volgende code produceert nu C2065:

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

    U kunt dit probleem oplossen door de juiste forward-declaraties toe te voegen:

    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);
    
  • Consistentere afdwinging van functiepointertypen

    De volgende code produceert nu C2197:

    typedef int(*F1)(int);
    typedef int(*F2)(int, int);
    
    void func(F1 f, int v1, int v2)
    {
        f(v1, v2); // C2197
    }
    
  • Dubbelzinnige aanroepen naar overbelaste functies

    De volgende code produceert nu C266: 'N::bind': dubbelzinnige aanroep naar overbelaste functie

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

    Om de fout op te lossen, kunt u de aanroep volledig kwalificeren naar bind: N::bind(...). Als deze wijziging echter manifest is via een ongedeclareerde identifier (C2065), kan het gepast zijn dit met een using declaratie op te lossen.

    Dit patroon gebeurt vaak met ComPtr en andere typen in de Microsoft::WRL naamruimte.

  • Corrigeer onjuist adres van

    De volgende code produceert nu C2440: '=': kan niet converteren van 'type *' naar 'type'. Als u de fout wilt oplossen, wijzigt u &(type) in (type) en (&f()) in (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());
    }
    
  • Letterlijke tekenreeks is een constante matrix

    De volgende code produceert nu C2664: 'void f(void )': kan argument 1 niet converteren van 'const char ()[2]' naar 'void *'

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

    Als u de fout wilt oplossen, wijzigt u het parametertype van de functie in const void*, of wijzigt u de hoofdtekst van h zodat deze op dit voorbeeld lijkt:

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

    De volgende code produceert nu fout C3688: ongeldig letterlijk achtervoegsel 'L'; letterlijke operator of letterlijke operatorsjabloon 'operator ''L' niet gevonden

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

    Als u de fout wilt oplossen, wijzigt u de code om een spatie toe te voegen:

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

    In het bovenstaande MACRO voorbeeld worden niet meer geparseerd als twee tokens (een tekenreeks gevolgd door een macro). Nu wordt het als één enkele token UDL geïnterpreteerd. Hetzelfde geldt voor L""L"", die eerder is geparseerd als L"" en L", en nu wordt geparseerd als L""L" en "".

    Regels voor tekenreekssamenvoeging zijn ook in overeenstemming gebracht met de standaard, wat betekent dat L"a" "b" gelijk is aan L"ab". In eerdere edities van Visual Studio zijn geen samenvoeging van tekenreeksen met verschillende tekenbreedten geaccepteerd.

  • C++11 leeg teken verwijderd

    De volgende code produceert nu fout C2137: lege tekenconstante

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

    Als u de fout wilt oplossen, wijzigt u de code om de null expliciet te maken:

    bool check(wchar_t c){
        return c == L'\0';
    }
    
  • MFC-uitzonderingen kunnen niet op waarde worden afgevangen omdat ze niet kunnen worden gekopieerd

    De volgende code in een MFC-toepassing veroorzaakt nu fout C2316: 'D': kan niet worden opgevangen omdat destructor en/of kopieerconstructor niet toegankelijk of verwijderd zijn

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

    Als u de code wilt herstellen, kunt u het catch-blok wijzigen in catch (const D &) maar de betere oplossing is meestal de MFC TRY/CATCH-macro's te gebruiken.

  • alignof is nu een trefwoord

    De volgende code produceert nu fout C2332: 'klasse': ontbrekende tagnaam. Als u de code wilt herstellen, moet u de naam van de klasse wijzigen of, als de klasse hetzelfde werk uitvoert als alignof, vervangt u de klasse door het nieuwe trefwoord.

    class alignof{}
    
  • constexpr is nu een trefwoord

    De volgende code produceert nu fout C2059: syntaxisfout: ')'. Als u de code wilt herstellen, moet u de naam van functie- of variabelenamen wijzigen die worden aangeroepen constexpr.

    int constexpr() {return 1;}
    
  • Verplaatsbare typen kunnen niet const zijn

    Wanneer een functie een type retourneert dat is bedoeld om te worden verplaatst, mag het retourtype niet zijn const.

  • Verwijderde kopieconstructors

    De volgende code produceert nu C2280 'S::S(S &&)': een poging om te verwijzen naar een verwijderde functie:

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

    Als u de fout wilt oplossen, gebruikt u directe initialisatie voor S2:

    struct S{
        S(int, int);
        S(const S&) = delete;
        S(S&&) = delete;
    };
    
    S s2 = {2,3}; //OK
    
  • Conversie naar functiepointer wordt alleen gegenereerd wanneer er geen lambda-opname wordt gemaakt

    De volgende code produceert C2664 in Visual Studio 2015.

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

    Om de fout te herstellen, verwijder de = uit de opnamelijst.

  • Dubbelzinnige aanroepen met conversieoperators

    De volgende code produceert nu fout C2440: 'type cast': kan niet converteren van 'S2' naar 'S1':

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

    Als u de fout wilt oplossen, roept u de conversieoperator expliciet aan:

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

    De volgende code produceert nu fout C2593: 'operator =' is dubbelzinnig:

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

    Als u de fout wilt oplossen, roept u de conversieoperator expliciet aan:

    void f(S1 *p, S2 s)
    {
        *p = s.operator S1&();
    }
    
  • Herstel ongeldige kopie-initialisatie bij de initialisatie van niet-statische gegevensleden (NSDMI)

    De volgende code produceert nu fout C2664: 'S1::S1(S1 &&)': argument 1 van 'bool' kan niet worden geconverteerd naar 'const S1 &':

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

    Gebruik directe initialisatie om de fout op te lossen:

    struct S2 {
    S1 s1{true}; // OK
    };
    
  • Toegang tot constructors binnen decltype-verklaringen

    De volgende code produceert nu C2248: 'S::S': kan geen toegang krijgen tot privé lid dat in klasse 'S' is gedeclareerd.

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

    Als u de fout wilt oplossen, voegt u een vrienddeclaratie voor S2 in S:

    class S {
        S();
        friend class S2; // Make S2 a friend
    public:
        int i;
    };
    
  • Standaardctor van lambda wordt impliciet verwijderd

    De volgende code produceert nu fout C3497: u kunt geen exemplaar van een lambda maken:

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

    Om de fout te herstellen, moet u het aanroepen van de standaardconstructor verwijderen. Als de lambda niets vastlegt, kan deze worden omgezet in een functiepointer.

  • Lambdas met een verwijderde toewijzingsoperator

    De volgende code produceert nu fout 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);
    }
    

    Als u de fout wilt oplossen, vervangt u de lambda door een functorklasse of verwijdert u de noodzaak om de toewijzingsoperator te gebruiken.

  • Poging om een object te verplaatsen met een verwijderde kopieerconstructor

    De volgende code produceert nu fout C2280: 'moveable::moveable(const moveable &)': een poging om te verwijzen naar een verwijderde functie

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

    Als u de fout wilt oplossen, gebruikt u std::move in plaats daarvan:

    S(moveable && m) :
        m_m(std::move(m))
    
  • Lokale klasse kan niet verwijzen naar andere lokale klassen die later in dezelfde functie zijn gedefinieerd

    De volgende code produceert nu fout C2079: 's' maakt gebruik van niet-gedefinieerde struct 'main::S2'

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

    Als u de fout wilt oplossen, verplaatst u de definitie van S2:

    int main()
    {
        struct S2 { //moved up
        };
    
    struct S1 {
        void f() {
            S2 s;
            }
        };
    }
    
  • Kan geen beveiligde basisctor aanroepen in de hoofdtekst van de afgeleide ctor.

    De volgende code produceert nu fout C2248: 'S1::S1': geen toegang tot beveiligd lid dat is gedeclareerd in klasse 'S1'

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

    Als u de fout wilt oplossen, verwijdert u de aanroep naar S2 uit de constructor en plaatst u deze indien nodig in een andere functie.

  • {} voorkomt conversie naar aanwijzer

    De volgende code produceert nu C2439 'S::p': lid kan niet worden geïnitialiseerd

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

    Om de fout op te lossen, verwijdert u de accolades rond 0 of gebruikt u in plaats daarvan nullptr, zoals in dit voorbeeld wordt getoond.

    struct S {
        S() : p(nullptr) {}
        void *p;
    };
    
  • Onjuiste macrodefinitie en -gebruik met haakjes

    In het volgende voorbeeld wordt nu fout C2008 gegenereerd: ';': onverwacht in macrodefinitie

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

    Als u het probleem wilt oplossen, wijzigt u de bovenste regel in #define A();

    De volgende code produceert fout C2059: syntaxisfout: ')'

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

    Als u de code wilt herstellen, verwijdert u de spatie tussen A en ().

    De volgende code produceert fout C2091: de functie retourneert de functie:

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

    Als u de fout wilt oplossen, verwijdert u de haakjes na DECLARE in S: DECLARE;.

    De volgende code produceert fout C2062: type 'int' onverwacht

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

    Definieer A het volgende om het probleem op te lossen:

    #define A int
    
  • Extra parens in declaraties

    De volgende code produceert fout C2062: type 'int' onverwacht

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

    Als u de fout wilt oplossen, verwijdert u de haakjes rond j. Als de haakjes nodig zijn voor duidelijkheid, gebruikt u een typedef.

  • Compilergegenereerde constructors en __declspec(novtable)

    In Visual Studio 2015 is er een grotere kans dat door compiler gegenereerde inlineconstructors van abstracte klassen met virtuele basisklassen onjuist gebruik kunnen blootstellen van __declspec(novtable) wanneer ze worden gebruikt in combinatie met __declspec(dllimport).

  • auto vereist een enkele expressie bij direct-lijst-initialisatie

    De volgende code produceert nu fout C3518: 'testPositions': in een direct-list-initialisatiecontext kan het type voor 'auto' alleen worden afgeleid van één initialisatie-expressie

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

    Als u de fout wilt oplossen, kunt u als volgt initialiseren testPositions :

    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}
    };
    
  • Typen controleren versus aanwijzers voor typen voor is_convertible

    De volgende code zorgt ervoor dat de statische assertie mislukt.

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

    U lost de fout op door de static_assert aanwijzers D te vergelijken met en B2:

    static_assert(std::is_convertible<D*, B2*>::value, "fail");
    
  • __declspec(novtable) declaraties moeten consistent zijn

    __declspec declaraties moeten consistent zijn in alle bibliotheken. Met de volgende code wordt nu een ODR-schending (One Definition Rule) geproduceerd:

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

Conformiteitsverbeteringen in Update 1

  • Privéklassen voor virtuele basis en indirecte overname

    In eerdere versies van de compiler kon een afgeleide klasse lidfuncties van de indirect afgeleide private virtual basisklassen aanroepen. Dit oude gedrag is onjuist en voldoet niet aan de C++-standaard. De compiler accepteert geen code meer die op deze manier is geschreven en geeft als gevolg hiervan compilerfout C2280 uit.

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

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

    -of-

    class base;  // as above
    
    class middle : private virtual base {};
    class top : public virtual middle, private virtual bottom {};
    
    void destroy(top *p)
    {
        delete p;
    }
    
  • Overbelastingsoperator nieuw en operator verwijderen

    In eerdere versies van de compiler was het toegestaan dat de niet-lidoperator operator new en de niet-lidoperator operator delete statisch werden gedeclareerd, en werden gedeclareerd in andere namespaces dan de globale namespace. Dit oude gedrag heeft een risico gecreëerd dat het programma de implementatie van de new of delete operator die de programmeur bedoelde niet zou aanroepen, wat resulteert in een stil slecht runtimegedrag. De compiler accepteert geen code meer die op deze manier is geschreven en geeft in plaats daarvan compilerfout C2323.

    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.
    

    Voorbeeld (vóór)

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

    Voorbeeld (na)

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

    Hoewel de compiler geen specifieke diagnose geeft, wordt de inlineoperator new beschouwd als slecht gevormd.

  • Operatortype()' aanroepen (door de gebruiker gedefinieerde conversie) voor niet-klassetypen

    In eerdere versies van de compiler kon 'operator type()' worden aangeroepen voor niet-klassetypen terwijl dit stilletjes werd genegeerd. Dit oude gedrag creëerde een risico op het genereren van slechte code, wat leidde tot onvoorspelbaar uitvoeringsgedrag. De compiler accepteert geen code meer die op deze manier is geschreven en geeft compilerfout C2228.

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

    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'
    }
    
  • Redundante typenaam in uitgebreide typeaanduidingen

    Eerdere versies van de compiler stonden typename toe in een uitgebreide typespecificator, maar code die op deze manier is geschreven, is semantisch onjuist. De compiler accepteert in plaats daarvan geen code meer die op deze manier is geschreven en geeft in plaats daarvan compilerfout C3406 uit.

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

    Voorbeeld (vóór)

    template <typename class T>
    class container;
    

    Voorbeeld (na)

    template <class T>  // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case
    class container;
    
  • Type-afleiding van arrays uit een initialisatielijst

    Eerdere versies van de compiler bieden geen ondersteuning voor type aftrek van matrices uit een initialisatielijst. De compiler ondersteunt nu deze vorm van typeaftrek en als gevolg hiervan kunnen aanroepen naar functiesjablonen met behulp van initialisatielijsten nu dubbelzinnig zijn of kan er een andere overbelasting worden gekozen dan in eerdere versies van de compiler. Om deze problemen op te lossen, moet het programma nu expliciet de overbelasting opgeven die de programmeur bedoelde.

    Wanneer dit nieuwe gedrag leidt tot een overbelastingsresolutie, wordt een extra kandidaat overwogen die even goed is als de historische kandidaat. Dat maakt de aanroep dubbelzinnig en als gevolg daarvan geeft de compiler de foutmelding C2668.

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

    Voorbeeld 1: Dubbelzinnige aanroep naar overbelaste functie (vóór)

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

    Voorbeeld 1: dubbelzinnige aanroep naar overbelaste functie (na)

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

    Wanneer dit nieuwe gedrag ervoor zorgt dat bij de overbelastingsresolutie een extra kandidaat in aanmerking wordt genomen die een betere match is dan de historische kandidaat, verwijst de oproep ondubbelzinnig naar de nieuwe kandidaat, wat leidt tot een verandering in het programmagedrag die waarschijnlijk anders is dan de programmeur had bedoeld.

    Voorbeeld 2: wijziging in overbelastingsresolutie (vóór)

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

    Voorbeeld 2: wijziging in overbelastingsresolutie (na)

    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 });
    }
    
  • Herstel van schakelinstructiewaarschuwingen

    Een eerdere versie van de compiler heeft enkele waarschuwingen met betrekking tot switch instructies verwijderd. Deze waarschuwingen zijn nu hersteld. De compiler geeft nu de herstelde waarschuwingen uit en waarschuwingen met betrekking tot specifieke gevallen (inclusief de standaardcase) worden nu uitgegeven op de regel die de offending case bevat, in plaats van op de laatste regel van de switch-instructie. Als gevolg van het nu uitgeven van deze waarschuwingen op andere regels dan voorheen, kunnen waarschuwingen die eerder zijn onderdrukt door dat gebruik van #pragma warning(disable:####), niet langer zoals bedoeld onderdrukt worden. Om deze waarschuwingen te onderdrukken zoals bedoeld, kan het nodig zijn om de #pragma warning(disable:####) richtlijn naar een regel boven het eerste problematische geval te verplaatsen. Hier volgen de herstelde waarschuwingen:

    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
    

    Voorbeeld van C4063 (vóór)

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

    Voorbeeld van C4063 (na)

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

    Voorbeelden van de andere herstelde waarschuwingen worden weergegeven in hun documentatie.

  • #include: gebruik van bovenliggende map-aanduiding '..' in padnaam (alleen van invloed op /Wall/WX)

    In eerdere versies van de compiler werd het gebruik van de bovenliggende mapaanduiding '..' niet gedetecteerd. in de padnaam van #include richtlijnen. Code die op deze manier is geschreven, is meestal bedoeld om headers op te nemen die buiten het project bestaan door verkeerd gebruik te maken van project-relatieve paden. Dit oude gedrag heeft een risico gecreëerd dat het programma kan worden gecompileerd door een ander bronbestand op te nemen dan de programmeur bedoelde, of dat deze relatieve paden niet overdraagbaar zijn naar andere buildomgevingen. De compiler detecteert en waarschuwt nu de programmeur van code die op deze manier is geschreven en geeft een optionele compilerwaarschuwing C4464 uit, indien ingeschakeld.

    warning C4464: relative include path contains '..'
    

    Voorbeeld (vóór)

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

    Voorbeeld (na)

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

    Bovendien, hoewel de compiler geen specifieke diagnose geeft, raden we u ook aan om de bovenliggende map aanduiding '..' niet te gebruiken om de insluitmappen van uw project op te geven.

  • #pragma optimize() breidt het einde van het headerbestand uit (alleen van invloed op /Wall/WX)

    In eerdere versies van de compiler werden geen wijzigingen in de instellingen van optimalisatievlaggen gedetecteerd die buiten de grenzen van een headerbestand vielen dat binnen een vertalingseenheid is opgenomen. De compiler detecteert en waarschuwt nu de programmeur van code die op deze manier is geschreven en geeft een optionele compilerwaarschuwing C4426 uit op de locatie van de offending #include, indien ingeschakeld. Deze waarschuwing wordt alleen weergegeven als de wijzigingen conflicteren met de optimalisatievlagken die zijn ingesteld door opdrachtregelargumenten voor de compiler.

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

    // 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"
    
  • Niet-overeenkomende #pragma waarschuwing (push) en #pragma waarschuwing (pop) ( alleen van invloed op /Wall/WX)

    In eerdere versies van de compiler zijn geen statuswijzigingen gedetecteerd #pragma warning(push) die worden gekoppeld aan #pragma warning(pop) statuswijzigingen in een ander bronbestand. Dit is zelden bedoeld. Dit oude gedrag heeft een risico gecreëerd dat het programma wordt gecompileerd met een andere set waarschuwingen die zijn ingeschakeld dan de programmeur bedoelde, wat mogelijk resulteert in een stil slecht runtime-gedrag. De compiler detecteert en waarschuwt nu de programmeur van code die op deze manier is geschreven en geeft een optionele compilerwaarschuwing C5031 uit op de locatie van de overeenkomende #pragma warning(pop), indien ingeschakeld. Deze waarschuwing bevat een opmerking die verwijst naar de locatie van de bijbehorende #pragma warning(push).

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

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

    Hoewel ongebruikelijk, is code die op deze manier is geschreven soms opzettelijk. Code die op deze manier is geschreven, is gevoelig voor wijzigingen in #include volgorde. Indien mogelijk raden we u aan om de waarschuwingsstatus van broncodebestanden op een zelfstandige manier te beheren.

  • In eerdere versies van de compiler zijn geen niet-overeenkomende #pragma warning(push) statuswijzigingen aan het einde van een vertaaleenheid gedetecteerd. De compiler detecteert en waarschuwt nu de programmeur van code die op deze manier is geschreven en geeft een optionele compilerwaarschuwing C5032 uit op de locatie van de niet-overeenkomende #pragma warning(push), indien ingeschakeld. Deze waarschuwing wordt alleen afgegeven als er geen compilatiefouten in de vertaaleenheid zijn.

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

    // 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)
    
  • Er kunnen extra waarschuwingen worden uitgegeven als gevolg van verbeterde #pragma tracering van waarschuwingsstatussen

    Eerdere versies van de compiler hielden de statusveranderingen van #pragma-waarschuwingen onvoldoende goed bij om alle beoogde waarschuwingen te geven. Dit gedrag heeft een risico gecreëerd dat bepaalde waarschuwingen effectief worden onderdrukt in andere omstandigheden dan de programmeur. De compiler houdt #pragma warning nu de status robuuster bij , met name gerelateerd aan #pragma warning statuswijzigingen in sjablonen - en geeft optioneel nieuwe waarschuwingen C5031 en C5032, die zijn bedoeld om de programmeur te helpen onbedoeld gebruik van #pragma warning(push) en #pragma warning(pop)te vinden.

    Als gevolg van verbeterde tracering van statuswijzigingen kunnen waarschuwingen die voorheen onterecht werden onderdrukt, of waarschuwingen met betrekking tot problemen die eerder verkeerd werden gediagnosticeerd, nu worden uitgegeven.

  • Verbeterde identificatie van onbereikbare code

    Wijzigingen in de standaardbibliotheek van C++ en de verbeterde mogelijkheid om functieaanroepen in-lijn te brengen in vergelijking met eerdere versies van de compiler, kunnen de compiler bewijzen dat bepaalde code nu onbereikbaar is. Dit nieuwe gedrag kan leiden tot nieuwe en vaker uitgegeven exemplaren van waarschuwing C4720.

    warning C4720: unreachable code
    

    In veel gevallen kan deze waarschuwing alleen worden uitgegeven bij het compileren met optimalisaties ingeschakeld, omdat optimalisaties meer functieaanroepen kunnen inlineen, redundante code elimineren of anderszins het mogelijk maken om te bepalen dat bepaalde code onbereikbaar is. We hebben vastgesteld dat er vaak nieuwe gevallen van waarschuwing C4720 in try/catch-blokken zijn opgetreden, vooral bij het gebruik van std::find.

    Voorbeeld (vóór)

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

    Voorbeeld (na)

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

Nalevingsverbeteringen in Update 2

  • Aanvullende waarschuwingen en fouten kunnen worden uitgegeven als gevolg van gedeeltelijke ondersteuning voor expressie SFINAE

    Eerdere versies van de compiler parseerde bepaalde soorten expressies niet binnen decltype de aanduidingen vanwege gebrek aan ondersteuning voor expressie SFINAE. Dit oude gedrag is onjuist en voldoet niet aan de C++-standaard. De compiler parseert deze expressies nu en biedt gedeeltelijke ondersteuning voor expressie-SFINAE vanwege doorlopende verbeteringen in de conformiteit. Als gevolg hiervan geeft de compiler nu waarschuwingen en fouten uit in expressies die in eerdere versies van de compiler niet zijn geparseerd.

    Wanneer dit nieuwe gedrag een decltype expressie parseert die een type bevat dat nog niet is gedeclareerd, geeft de compiler een compilerfout C2039 als gevolg hiervan.

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

    Voorbeeld 1: gebruik van een niet-gedeclareerd type (voorheen)

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

    Voorbeeld 1 (na)

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

    Wanneer dit nieuwe gedrag een decltype-expressie parseert waarvoor het noodzakelijk gebruik van het typename-trefwoord ontbreekt, om op te geven dat een afhankelijke naam een type is, geeft de compiler compilerwaarschuwing C4346 samen met compilerfout 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'
    

    Voorbeeld 2: afhankelijke naam is geen type (voorheen)

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

    Voorbeeld 2 (na)

    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 lidvariabelen voorkomen impliciet gedefinieerde constructors en toewijzingsoperatoren

    In eerdere versies van de compiler stond een klasse met volatile lidvariabelen toe om standaard kopie-/verplaatsingsconstructors en standaardoperators voor kopiëren/verplaatsen automatisch te genereren. Dit oude gedrag is onjuist en voldoet niet aan de C++-standaard. De compiler beschouwt nu een klasse met volatile lidvariabelen om niet-triviale bouw- en toewijzingsoperatoren te hebben, waardoor standaard implementaties van deze operators niet automatisch worden gegenereerd. Wanneer een dergelijke klasse lid is van een union (of een anonieme samenvoeging binnen een klasse), worden de copy/move constructors en copy/move-toewijzingsoperators van de union (of de klasse met de anonieme samenvoeging) impliciet gedefinieerd als verwijderd. Een poging om de samenvoeging (of klasse met de anonieme samenvoeging) te maken of te kopiëren zonder deze expliciet te definiëren, is een fout en de compiler veroorzaakt compilerfout C2280 als gevolg hiervan.

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

    Voorbeeld (vóór)

    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
    

    Voorbeeld (na)

    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
    
  • Statische lidfuncties bieden geen ondersteuning voor cv-qualifiers.

    In eerdere versies van Visual Studio 2015 mochten statische lidfuncties cv-kwalificaties hebben. Dit gedrag wordt veroorzaakt door een regressie in Visual Studio 2015 en Visual Studio 2015 Update 1; Visual Studio 2013 en eerdere versies van de compiler weigeren code die op deze manier is geschreven. Het gedrag van Visual Studio 2015 en Visual Studio 2015 Update 1 is onjuist en voldoet niet aan de C++-standaard. Visual Studio 2015 Update 2 weigert code die op deze manier is geschreven en geeft in plaats daarvan compilerfout C2511.

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

    struct A
    {
        static void func();
    };
    
    void A::func() {}  // removed const
    
  • Forward-declaratie van enum is niet toegestaan in WinRT-code (alleen van invloed op /ZW)

    Met code die is gecompileerd voor Windows Runtime (WinRT) kunnen enum typen niet vooruit worden gedeclareerd, net zoals wanneer beheerde C++-code voor het .Net Framework wordt gecompileerd met de /clr compilerswitch. Dit gedrag zorgt ervoor dat de grootte van een opsomming altijd bekend is en correct kan worden geprojecteerd naar het WinRT-typesysteem. De compiler weigert op deze manier geschreven code en geeft compilerfout C2599 samen met compilerfout C3197 uit.

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

              // forward declaration of CustomEnum removed
    namespace A {
        public enum class CustomEnum : int32
        {
            Value1
        };
    }
    
    public ref class Component sealed
    {
    public:
        CustomEnum f()
        {
            return CustomEnum::Value1;
        }
    };
    
  • Overbelaste niet-lidoperatoren new en delete mogen niet inline worden gedeclareerd (niveau 1 (/W1) on-by-default)

    In eerdere versies van de compiler wordt geen waarschuwing weergegeven wanneer niet-lidoperator new- en operator delete-functies inline worden gedeclareerd. Code die op deze manier is geschreven, is slecht gevormd (geen diagnostische gegevens vereist) en kan geheugenproblemen veroorzaken als gevolg van niet-overeenkomende nieuwe en verwijder operators (vooral wanneer ze samen met het vrijgeven van geheugen met grootte worden gebruikt) die moeilijk te bepalen zijn. De compiler geeft nu compilerwaarschuwing C4595 uit om code te identificeren die op deze manier is geschreven.

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

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

    Het herstellen van code die op deze manier is geschreven, kan vereisen dat de operatordefinities worden verplaatst uit een headerbestand en naar een bijbehorend bronbestand.

Nalevingsverbeteringen in Update 3

  • std::is_convertable detecteert nu zelftoewijzing (standaardbibliotheek)

    In eerdere versies van de std::is_convertable type-eigenschap is de zelftoewijzing van een klassetype niet correct gedetecteerd wanneer de kopieerconstructor wordt verwijderd of privé is. Nu wordt std::is_convertable<>::value correct ingesteld op false wanneer dit wordt toegepast op een klassetype met een verwijderde of private kopieerconstructor.

    Er is geen compilerdiagnose gekoppeld aan deze wijziging.

    Voorbeeld

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

    In eerdere versies van de compiler slagen de statische asserties onder aan dit voorbeeld omdat std::is_convertable<>::value onjuist was ingesteld als true. Nu is std::is_convertable<>::value correct ingesteld op false, waardoor de statische asserties mislukken.

  • Gedefaulteerde of verwijderde triviale kopieer- en verplaatsingsconstructors respecteren toegangsspecificaties

    In eerdere versies van de compiler is de toegangsaanduiding van standaard- of verwijderde triviale kopieer- en verplaatsingsconstructors niet gecontroleerd voordat ze kunnen worden aangeroepen. Dit oude gedrag is onjuist en voldoet niet aan de C++-standaard. In sommige gevallen heeft dit oude gedrag een risico op het genereren van ongeldige code veroorzaakt, wat resulteert in onvoorspelbaar runtimegedrag. De compiler controleert nu de toegangsaanduiding van standaard- of verwijderde triviale kopieer- en verplaatsingsconstructors om te bepalen of deze kan worden aangeroepen; zo niet, geeft compilerwaarschuwing C2248.

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

    Voorbeeld (vóór)

    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
    }
    

    Voorbeeld (na)

    class S {
    public:
        S() = default;
    private:
        S(const S&) = default;
    };
    
    void f(const S&);  // pass S by reference
    
    int main()
    {
        S s;
        f(s);
    }
    
  • Afschaffing van toegewezen ATL-codeondersteuning (niveau 1 (/W1) on-by-default)

    Eerdere versies van de compiler ondersteunden toegeschreven ATL-code. Als de volgende fase van het verwijderen van ondersteuning voor toegeschreven ATL-code die is begonnen in Visual Studio 2008, is toegeschreven ATL-code verouderd. De compiler geeft nu compilerwaarschuwing C4467 op om dit soort afgeschafte code te identificeren.

    warning C4467: Usage of ATL attributes is deprecated
    

    Als u ATL-code wilt blijven gebruiken totdat de ondersteuning van de compiler wordt verwijderd, kunt u deze waarschuwing uitschakelen door de /Wv:18 argumenten of /wd:4467 opdrachtregelargumenten door te geven aan de compiler of door de broncode toe te voegen #pragma warning(disable:4467) .

    Voorbeeld 1 (vóór)

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

    Voorbeeld 1 (na)

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

    Soms hebt u mogelijk een IDL-bestand nodig of wilt maken om het gebruik afgeschafte ATL-kenmerken te voorkomen, zoals in de onderstaande voorbeeldcode

    Voorbeeld 2 (vóór)

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

    Maak eerst het *.idl-bestand; het gegenereerde bestand vc140.idl kan worden gebruikt om een *.idl-bestand met de interfaces en aantekeningen te verkrijgen.

    Voeg vervolgens een MIDL-stap toe aan uw build om ervoor te zorgen dat de C++-interfacedefinities worden gegenereerd.

    Voorbeeld 2 IDL (na)

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

    Gebruik VERVOLGENS ATL rechtstreeks in het implementatiebestand, zoals in de onderstaande voorbeeldcode.

    Voorbeeld 2 Implementatie (na)

    #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()
    };
    
  • PcH-bestanden (precompiled header) en niet-overeenkomende #include instructies ( alleen van invloed op /Wall/WX)

    In eerdere versies van de compiler zijn niet-overeenkomende #include instructies in bronbestanden tussen -Yc en -Yu compilaties geaccepteerd wanneer u pcH-bestanden (precompiled header) gebruikt. Code die op deze manier is geschreven, wordt niet meer geaccepteerd door de compiler. De compiler geeft nu compilerwaarschuwing CC4598 op om niet-overeenkomende #include instructies te identificeren bij het gebruik van PCH-bestanden.

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

    Voorbeeld (vóór):

    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"
    

    Voorbeeld (na)

    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"
    
  • Precompiled header (PCH)-bestanden en niet-overeenkomende include-mappen (alleen van invloed op /Wall/WX)

    Eerdere versies van de compiler accepteerden niet-overeenkomende includemappen (-I) als opdrachtregelargumenten voor de compiler tussen -Yc en -Yu compilaties bij het gebruik van vooraf gecompileerde header-bestanden (PCH). Code die op deze manier is geschreven, wordt niet meer geaccepteerd door de compiler. De compiler geeft nu een compilerwaarschuwing CC4599, die helpt bij het identificeren van niet-overeenkomende include-directory's (-I) opdrachtregelargumenten wanneer PCH-bestanden worden gebruikt.

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

    Voorbeeld (vóór)

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

    Voorbeeld (na)

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

Wijzigingen in de conformiteit van Visual Studio 2013

Samensteller

  • Met het laatste trefwoord wordt nu een onopgeloste symboolfout gegenereerd, waar deze eerder zou zijn gecompileerd:

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

    In eerdere versies is er geen fout uitgegeven omdat de aanroep een virtual aanroep was. Toch loopt het programma vast tijdens runtime. Er wordt nu een linker-error weergegeven omdat de klasse final is. In dit voorbeeld, om de fout op te lossen, zou u koppelen aan het object dat de definitie van S2::f bevat.

  • Wanneer u vriendfuncties in naamruimten gebruikt, moet u de functie vriend opnieuw declareren voordat u ernaar verwijst of u krijgt een foutmelding omdat de compiler nu voldoet aan de ISO C++-standaard. In dit voorbeeld worden bijvoorbeeld niet meer gecompileerd:

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

    Als u deze code wilt corrigeren, declareert u de friend functie:

    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);
        }
    
  • De C++ Standard staat geen expliciete specialisatie toe in een klasse. Hoewel de Microsoft C++-compiler het in sommige gevallen toestaat, wordt er in gevallen zoals het volgende voorbeeld een fout gegenereerd omdat de compiler niet van mening is dat de tweede functie een specialisatie van de eerste functie is.

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

    Wijzig de tweede functie om deze code te corrigeren:

    template <> void f(char& val);
    
  • De compiler probeert de twee functies in het volgende voorbeeld niet meer ondubbelzinnig te maken en verzendt nu een fout:

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

    Om deze code te corrigeren, moet u de aanroep verduidelijken:

    template< typename T> void Func(T* t = nullptr);
    template< typename T> void Func(...);
    
    int main() {
        Func< int>(nullptr); // ok
    }
    
  • Voordat de compiler voldoet aan ISO C++11, zou de volgende code zijn gecompileerd en veroorzaakt x om te worden omgezet in het type int:

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

    Deze code wordt nu omgezet x in een type std::initializer_list<int> en veroorzaakt een fout op de volgende regel die probeert toe te wijzen x aan het type int. (Er is standaard geen conversie.) Als u deze code wilt corrigeren, gebruikt int u om het volgende te vervangen auto:

    int x = {0};
    int y = x;
    
  • Aggregatie-initialisatie is niet meer toegestaan wanneer het type van de rechterwaarde niet overeenkomt met het type van de linkerwaarde die wordt geïnitialiseerd en er een fout wordt weergegeven omdat de ISO C++11-standaard uniforme initialisatie vereist om te werken zonder conversies te beperken. Als er eerder een narrowing-conversie beschikbaar was, zou er een C4242-waarschuwing voor compiler (niveau 4) zijn uitgegeven in plaats van een fout.

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

    Als u deze code wilt corrigeren, voegt u een expliciete vermalingsconversie toe:

    int i = 0;
    char c = {static_cast<char>(i)};
    
  • De volgende initialisatie is niet meer toegestaan:

    void *p = {{0}};
    

    Als u deze code wilt corrigeren, gebruikt u een van de volgende formulieren:

    void *p = 0;
    // or
    void *p = {0};
    
  • Naamzoekactie is gewijzigd. De volgende code wordt anders opgelost in de C++-compiler in Visual Studio 2012 en Visual Studio 2013:

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

    In Visual Studio 2012 is de E1 in-expressie E1::b omgezet in ::E1 het globale bereik. In Visual Studio 2013 wordt E1 in de expressie E1::b omgezet in de definitie typedef E2 in main() en heeft het type ::E2.

  • De objectindeling is gewijzigd. Op x64 kan de objectindeling van een klasse veranderen ten opzichte van eerdere releases. Als deze een virtual functie heeft maar geen basisklasse heeft die een virtual functie heeft, wordt met het objectmodel van de compiler een aanwijzer naar een virtual functietabel ingevoegd na de indeling van het gegevenslid. Dit betekent dat de indeling in alle gevallen niet optimaal is. In eerdere versies zou een optimalisatie voor x64 proberen de indeling voor u te verbeteren, maar omdat deze niet correct werkt in complexe codesituaties, is deze verwijderd in Visual Studio 2013. Denk bijvoorbeeld aan deze code:

    __declspec(align(16)) struct S1 {
    };
    
    struct S2 {
        virtual ~S2();
        void *p;
        S1 s;
    };
    
  • In Visual Studio 2013 is het resultaat van sizeof(S2) op x64 48, maar in eerdere releases is het 32. Als u dit wilt evalueren naar 32 in de C++-compiler van Visual Studio 2013 voor x64, voegt u een dummy-basisklasse met een virtual functie toe:

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

    Als u locaties in uw code wilt vinden die een eerdere versie zou hebben geprobeerd te optimaliseren, gebruikt u een compiler uit die release samen met de /W3 compileroptie en schakelt u waarschuwing C4370 in. Voorbeeld:

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

    Voordat Visual Studio 2013 werd dit bericht weergegeven: 'waarschuwing C4370: 'S2': de indeling van de klasse is gewijzigd ten opzichte van een vorige versie van de compiler vanwege een optimalere opmaak.'

    De x86-compiler heeft hetzelfde suboptimale indelingsprobleem in alle versies van de compiler. Als deze code bijvoorbeeld is gecompileerd voor x86:

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

    Het resultaat van sizeof(S) is 24. Het kan echter worden teruggebracht tot 16 als u de tijdelijke oplossing gebruikt die wordt vermeld voor x64:

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

Standaardbibliotheek

De C++-compiler in Visual Studio 2013 detecteert niet-overeenkomende items in _ITERATOR_DEBUG_LEVEL, die in Visual Studio 2010 is geïmplementeerd en RuntimeLibrary komt niet overeen. Deze verschillen komen niet overeen wanneer compileropties /MT (statische release), /MTd (statische foutopsporing), /MD (dynamische release) en /MDd (dynamische foutopsporing) gemengd zijn.

  • Als uw code de gesimuleerde aliassjablonen van de vorige release bevestigt, moet u deze wijzigen. In plaats van allocator_traits<A>::rebind_alloc<U>::otherbijvoorbeeld, moet je nu zeggen allocator_traits<A>::rebind_alloc<U>. Hoewel ratio_add<R1, R2>::type niet meer nodig is en we u nu aanraden om ratio_add<R1, R2> te zeggen, zal de eerdere nog steeds worden gecompileerd omdat ratio<N, D> een typedef moet hebben voor een gereduceerde verhouding, wat hetzelfde type zal zijn als het al is gereduceerd.

  • U moet gebruiken #include <algorithm> wanneer u belt std::min() of std::max().

  • Als uw bestaande code gebruikmaakt van gesimuleerde 'scoped enums'—traditionele ongeassocieerde enums in namespaces—moet u deze wijzigen. Als u bijvoorbeeld naar het type std::future_status::future_statushebt verwezen, moet u nu zeggen std::future_status. De meeste code wordt echter niet beïnvloed, bijvoorbeeld std::future_status::ready nog steeds compileert.

  • explicit operator bool() is strenger dan de operator zonder opgegeven bool-type(). explicit operator bool() staat expliciete conversies toe aan bool, bijvoorbeeld, shared_ptr<X> spzowel static_cast<bool>(sp) als bool b(sp) geldig, en booleaanse testbare 'contextuele conversies' aan bool, bijvoorbeeld if (sp), , !spwat sp && dan ook. explicit operator bool() verbiedt echter impliciete conversies naar bool, dus je kunt niet zeggen bool b = sp; en met een bool-retvaltyp kun je niet zeggen return sp.

  • Nu echte variadic sjablonen zijn geïmplementeerd, hebben _VARIADIC_MAX en gerelateerde macro's geen effect. Als u nog steeds _VARIADIC_MAX definieert, wordt deze genegeerd. Als u onze macro's hebt gebruikt die bedoeld zijn ter ondersteuning van gesimuleerde variadic templates op een andere wijze, moet u uw code wijzigen.

  • Naast gewone trefwoorden verbieden C++ Standaardbibliotheekkoppen nu de macrovervanging van de contextgevoelige trefwoorden overschrijven en definitief.

  • reference_wrapper, ref()en cref() verbied nu binding met tijdelijke objecten.

  • <random> handhaaft nu strikt zijn compile-tijd voorwaarden.

  • Verschillende kenmerken van het type C++ Standaardbibliotheek hebben de voorwaarde "T moet een volledig type zijn". Hoewel de compiler deze voorwaarde nu strikter afdwingt, wordt deze mogelijk niet in alle situaties afgedwongen. (Omdat schendingen van voorwaarden voor C++-standaardbibliotheek niet-gedefinieerd gedrag veroorzaken, garandeert de Standaard geen afdwinging.)

  • De C++-standaardbibliotheek biedt geen ondersteuning voor /clr:oldSyntax.

  • De C++11-specificatie voor common_type<> had onverwachte en ongewenste gevolgen; met name zorgt het ervoor dat common_type<int, int>::typeint&& retourneert. Daarom implementeert de compiler de voorgestelde oplossing voor Bibliotheekwerk groepskwestie 2141, zodat common_type<int, int="">::typeint retourneert.

    Als neveneffect van deze wijziging werkt de identiteitscase niet meer (common_type<T> resulteert niet altijd in type T). Dit gedrag voldoet aan de voorgestelde oplossing, maar breekt alle code die afhankelijk is van het vorige gedrag.

    Als u een kenmerk van het identiteitstype nodig hebt, gebruik niet de niet-standaard std::identity die is gedefinieerd in <type_traits>, omdat deze niet werkt voor <void>. Implementeer in plaats daarvan uw eigen identiteitstype om aan uw behoeften tegemoet te komen. Hier is een voorbeeld:

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

MFC en ATL

  • Alleen Visual Studio 2013: MFC MBCS Library is niet opgenomen in Visual Studio omdat Unicode zo populair is en het gebruik van MBCS aanzienlijk is gedaald. Deze wijziging houdt MFC ook nauwer afgestemd op de Windows SDK zelf, omdat veel van de nieuwe besturingselementen en berichten alleen Unicode zijn. Als u echter de MFC MBCS-bibliotheek moet blijven gebruiken, kunt u deze downloaden via het Microsoft Downloadcentrum bij Multibyte MFC Library voor Visual Studio 2013. Het Herdistribueerbare pakket van Visual C++ bevat nog steeds deze bibliotheek. (Opmerking: de MBCS-DLL is opgenomen in de C++-installatieonderdelen in Visual Studio 2015 en hoger).

  • Toegankelijkheid voor het MFC-lint wordt gewijzigd. In plaats van een architectuur op één niveau is er nu een hiërarchische architectuur. U kunt het oude gedrag nog steeds gebruiken door aan te roepen CRibbonBar::EnableSingleLevelAccessibilityMode().

  • De methode CDatabase::GetConnect wordt verwijderd. Ter verbetering van de beveiliging wordt de verbindingsreeks nu versleuteld opgeslagen en wordt deze alleen ontsleuteld als dat nodig is; het kan niet worden geretourneerd als tekst zonder opmaak. De tekenreeks kan worden verkregen door de CDatabase::Dump functie te gebruiken.

  • CWnd::OnPowerBroadcast De handtekening is gewijzigd. De handtekening van deze berichtenhandler wordt gewijzigd om een LPARAM als de tweede parameter te gebruiken.

  • Handtekeningen worden gewijzigd om ruimte te bieden aan berichthandlers. De parameterlijsten van de volgende functies zijn gewijzigd om nieuw toegevoegde ON_WM_* berichthandlers te gebruiken:

    • CWnd::OnDisplayChange gewijzigd in (UINT, int, int) in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_DISPLAYCHANGE macro te gebruiken is in de berichtenmap.

    • CFrameWnd::OnDDEInitiate gewijzigd in (CWnd*, UINT, UNIT) in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_DDE_INITIATE macro kan worden gebruikt in de berichtenkaart.

    • CFrameWnd::OnDDEExecute gewijzigd in (CWnd*, HANDLE) in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_DDE_EXECUTE macro kan worden gebruikt in de berichtenmap.

    • CFrameWnd::OnDDETerminate gewijzigd in (CWnd*) als de parameter in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_DDE_TERMINATE macro kan worden gebruikt in de berichtkaart.

    • CMFCMaskedEdit::OnCut gewijzigd in geen parameters in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_CUT macro kan worden gebruikt in de berichtkaart.

    • CMFCMaskedEdit::OnClear gewijzigd naar geen parameters in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_CLEAR macro kan worden gebruikt in de berichtmap.

    • CMFCMaskedEdit::OnPaste gewijzigd naar geen parameters in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_PASTE macro in de berichtenmap kan worden gebruikt.

  • #ifdef instructies in de MFC-headerbestanden worden verwijderd. Talrijke #ifdef instructies in de MFC-headerbestanden met betrekking tot niet-ondersteunde versies van Windows (WINVER < 0x0501) worden verwijderd.

  • ATL DLL (atl120.dll) wordt verwijderd. ATL wordt nu geleverd als headers en een statische bibliotheek (atls.lib).

  • Atlsd.lib, atlsn.lib en atlsnd.lib worden verwijderd. Atls.lib heeft geen afhankelijkheden meer van tekenset of code die specifiek is voor foutopsporing/release. Omdat deze werkt voor Unicode/ANSI en foutopsporing/release, is slechts één versie van de bibliotheek vereist.

  • HET hulpprogramma ATL/MFC Trace wordt samen met de ATL DLL verwijderd en het traceringsmechanisme wordt vereenvoudigd. De CTraceCategory constructor heeft nu één parameter (de categorienaam) en de TRACE-macro's roepen de crt-foutopsporingsrapportagefuncties aan.

Wijzigingen die fouten veroorzaken in Visual Studio 2012

Samensteller

  • De /Yl compileroptie is gewijzigd. De compiler maakt standaard gebruik van deze optie, wat kan leiden tot LNK2011 fouten onder bepaalde voorwaarden. Zie /Yl (Inject PCH Reference for Debug Library) voor meer informatie.

  • In code die is gecompileerd met behulp van /clr, definieert het enum klassetrefwoord een C++11-enum, niet een COMMON Language Runtime -opsomming (CLR). Als u een CLR-opsomming wilt definiëren, moet u expliciet zijn over de toegankelijkheid ervan.

  • Gebruik het sleutelwoord 'template' om een afhankelijke naam expliciet te onderscheiden (conformiteit met de C++ Language Standard). In het volgende voorbeeld is het gemarkeerde sjabloonwoord verplicht om de dubbelzinnigheid op te lossen. Zie Naamomzetting voor afhankelijke typen voor meer informatie.

    template < typename X = "", typename = "" AY = "">
    struct Container { typedef typename AY::template Rebind< X> ::Other AX; };
    
  • Constante expressie van het type float is niet meer toegestaan als sjabloonargument, zoals wordt weergegeven in het volgende voorbeeld.

    template<float n=3.14>
    struct B {};  // error C2993: 'float': illegal type for non-type template parameter 'n'
    
  • Code die is gecompileerd met behulp van de /GS opdrachtregeloptie en die een off-by-one-kwetsbaarheid heeft, kan leiden tot het beëindigen van processen tijdens runtime, zoals getoond in het volgende pseudocodevoorbeeld.

    char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminate
    
  • De standaardarchitectuur voor x86-builds wordt gewijzigd in SSE2; Daarom kan de compiler SSE-instructies verzenden en de XMM-registers gebruiken om berekeningen met drijvende komma uit te voeren. Als u het vorige gedrag wilt herstellen, gebruikt u de /arch:IA32 compilervlag om de architectuur op te geven als IA32.

  • De compiler kan waarschuwingen compilerwaarschuwingen (niveau 4) C4703 en C4701 uitgeven, waar het eerder niet was. De compiler past sterkere controles toe op het gebruik van niet-geïnitialiseerde lokale variabelen van het type aanwijzer.

  • Wanneer de nieuwe linkervlag /HIGHENTROPYVA is opgegeven, zorgt Windows 8 er doorgaans voor dat geheugentoewijzingen een 64-bits adres retourneren. (Vóór Windows 8 hebben dergelijke toewijzingen vaker adressen geretourneerd die kleiner waren dan 2 GB.) Deze wijziging kan fouten in de afkapping van aanwijzers in bestaande code blootstellen. Deze schakeloptie is standaard ingeschakeld. Als u dit gedrag wilt uitschakelen, geeft u /HIGHENTROPYVA:NOop.

  • De beheerde compiler (Visual Basic/C#) ondersteunt /HIGHENTROPYVA ook voor beheerde builds. In dit geval is de /HIGHENTROPYVAswitch standaardinstelling uitgeschakeld.

IDE

  • Hoewel u wordt aangeraden geen Windows Forms-toepassingen te maken in C++/CLI, wordt het onderhoud van bestaande C++/CLI UI-toepassingen ondersteund. Als u een Windows Forms-toepassing of een andere .NET UI-toepassing moet maken, gebruikt u C# of Visual Basic. Gebruik C++/CLI alleen voor interoperabiliteitsdoeleinden.

Bibliotheek met parallelle patronen en runtimebibliotheek voor gelijktijdigheid

De SchedulerType opsomming is UmsThreadDefault afgeschaft. Specificatie van UmsThreadDefault produceert een afgeschafte waarschuwing en wijst intern terug aan de ThreadScheduler.

Standaardbibliotheek

  • Na een belangrijke wijziging tussen de C++98/03- en C++11-standaarden, waarbij expliciete sjabloonargumenten worden gebruikt om aan te roepen make_pair() , zoals in make_pair<int, int>(x, y) , wordt doorgaans niet gecompileerd in Visual C++ in Visual Studio 2012. De oplossing is altijd aanroepen make_pair() zonder expliciete sjabloonargumenten, zoals in make_pair(x, y). Het gebruiken van expliciete sjabloonargumenten ondermijnt het doel van de functie. Gebruik pair in plaats van make_pair als u nauwkeurige controle over het resulterende type nodig hebt, zoals in pair<short, short>(int1, int2).

  • Een andere belangrijke wijziging tussen de C++98/03- en C++11-standaarden: Wanneer A impliciet converteerbaar is naar B en B impliciet converteerbaar is naar C, maar A niet impliciet converteerbaar is naar C, stonden C++98/03 en Visual Studio 2010 toe dat pair<A, X> (impliciet of expliciet) werd geconverteerd naar pair<C, X>. (Het andere type, X, is hier niet van belang en is niet specifiek voor het eerste type in het paar.) De C++-compiler in Visual Studio 2012 detecteert dat A niet impliciet converteert naar C en verwijdert de paarconversie van overbelastingsresolutie. Deze wijziging is een positief voor veel scenario's. Zo zal overloading van func(const pair<int, int>&) en func(const pair<string, string>&), en het aanroepen van func() met pair<const char *, const char *> worden gecompileerd met deze wijziging. Deze wijziging onderbreekt echter code die afhankelijk is van agressieve paarconversies. Dergelijke code kan doorgaans worden verholpen door één deel van de conversie expliciet uit te voeren, bijvoorbeeld door door te geven make_pair(static_cast<B>(a), x) aan een functie die verwacht pair<C, X>.

  • Visual Studio 2010 gesimuleerde variadic-sjablonen, bijvoorbeeld make_shared<T>(arg1, arg2, argN), tot een limiet van 10 argumenten, door overbelastingen en specialisaties met preprocessormachines uit te stempelen. In Visual Studio 2012 wordt deze limiet beperkt tot vijf argumenten om de compilatietijden en het geheugenverbruik van de compiler voor het merendeel van de gebruikers te verbeteren. U kunt de vorige limiet echter projectbreed instellen door _VARIADIC_MAX als 10 expliciet te definiëren.

  • C++11 17.6.4.3.1 [macro.names]/2 verbiedt macrovervanging van trefwoorden wanneer C++ Standaardbibliotheekheaders zijn opgenomen. De headers verzenden nu compilerfouten als ze trefwoorden detecteren die door macro's zijn vervangen. (Als u _ALLOW_KEYWORD_MACROS definieert, kan dergelijke code worden gecompileerd, maar we raden het gebruik ten zeer zeere af.) Als uitzondering is de macrovorm standaard new toegestaan, omdat de kopteksten zichzelf uitgebreid verdedigen met behulp van#pragma push_macro("new")/#undef new/#pragma pop_macro("new") . Het definiëren van _ENFORCE_BAN_OF_MACRO_NEW doet precies wat de naam ervan inhoudt.

  • Voor het implementeren van verschillende optimalisaties en foutopsporingscontroles wordt de binaire compatibiliteit tussen versies van Visual Studio (2005, 2008, 2010, 2010, 2012) opzettelijk verbroken door de implementatie van de standaardbibliotheek van C++ . Wanneer de standaardbibliotheek van C++ wordt gebruikt, verbiedt deze het combineren van objectbestanden en statische bibliotheken die zijn gecompileerd met behulp van verschillende versies in één binair (EXE of DLL) en verbiedt het doorgeven van C++ Standard Library-objecten tussen binaire bestanden die worden gecompileerd met behulp van verschillende versies. Het combineren van objectbestanden en statische bibliotheken die gebruikmaken van de C++-standaardbibliotheek, gecompileerd met Visual Studio 2010, met die gecompileerd met de C++-compiler in Visual Studio 2012, leidt tot linkerfouten over een _MSC_VER-mismatch. Hierbij is _MSC_VER de macro die het hoofdversienummer van de compiler bevat (1700 voor Visual C++ in Visual Studio 2012). Met deze controle kan DLL-menging niet worden gedetecteerd en kan geen menging worden gedetecteerd waarbij Visual Studio 2008 of eerder is betrokken.

  • Naast het detecteren van _ITERATOR_DEBUG_LEVEL-niveaus die niet overeenkomen, wat werd geïmplementeerd in Visual Studio 2010, detecteert de C++-compiler in Visual Studio 2012 mismatches in de runtimebibliotheek. Deze verschillen komen niet overeen wanneer de compileropties /MT (statische release), /MTd (statische foutopsporing), /MD (dynamische release) en /MDd (dynamische foutopsporing) worden gemengd.

  • operator<(), , operator>()operator<=()en operator>=() waren eerder beschikbaar voor de std::unordered_map en stdext::hash_map families van containers, hoewel hun implementaties niet nuttig waren. Deze niet-standaardoperators zijn verwijderd in Visual C++ in Visual Studio 2012. Daarnaast is de implementatie van operator==() en operator!=() voor de std::unordered_map familie uitgebreid om de stdext::hash_map familie te dekken. (U wordt aangeraden het gebruik van de stdext::hash_map familie in nieuwe code te vermijden.)

  • C++11 22.4.1.4 [locale.codecvt] geeft aan dat codecvt::length() en codecvt::do_length() wijzigbare stateT&-parameters moeten aannemen, maar Visual Studio 2010 nam const stateT&. De C++-compiler in Visual Studio 2012 accepteert stateT& zoals voorgeschreven door de standaard. Dit verschil is belangrijk voor iedereen die de virtuele functie do_length()probeert te overschrijven.

CRT

  • De CRT-heap (C Runtime), die wordt gebruikt voor new en malloc(), is niet langer privé. De CRT maakt nu gebruik van de proces-heap. Dit betekent dat de heap niet wordt vernietigd wanneer een DLL wordt ontladen, dus DLL's die statisch aan de CRT zijn gekoppeld, moeten ervoor zorgen dat het geheugen dat door de DLL-code wordt toegewezen, wordt opgeschoond voordat deze wordt ontladen.

  • De iscsymf() functie bevestigt met negatieve waarden.

  • De threadlocaleinfostruct struct is gewijzigd om de wijzigingen in landinstellingenfuncties aan te passen.

  • CRT-functies met bijbehorende intrinsiek zoals memxxx(), strxxx() worden verwijderd uit intrin.h. Als u alleen intrin.h voor deze functies hebt opgenomen, moet u nu de bijbehorende CRT-headers opnemen.

MFC en ATL

  • Fusion-ondersteuning verwijderd (afxcomctl32.h); daarom zijn alle methoden die in <afxcomctl32.h> zijn gedefinieerd, verwijderd. Koptekstbestanden <afxcomctl32.h> en <afxcomctl32.inl> zijn verwijderd.

  • De naam van CDockablePane::RemoveFromDefaultPaneDividier veranderd naar CDockablePane::RemoveFromDefaultPaneDivider.

  • De handtekening van CFileDialog::SetDefExt is gewijzigd naar het gebruik van LPCTSTR; hierdoor worden Unicode-builds beïnvloed.

  • Verouderde ATL-traceringscategorieën zijn verwijderd.

  • De signatuur van CBasePane::MoveWindow gewijzigd zodat deze een const CRect accepteert.

  • De handtekening van CMFCEditBrowseCtrl::EnableBrowseButton is veranderd.

  • Verwijderd m_fntTabs en m_fntTabsBold van CMFCBaseTabCtrl.

  • Er is een parameter toegevoegd aan de CMFCRibbonStatusBarPane constructors. (Het is een standaardparameter en is dus niet bronverbrekend.)

  • Er is een parameter toegevoegd aan de CMFCRibbonCommandsListBox constructor. (Het is een standaardparameter en is dus niet bronverbrekend.)

  • De AFXTrackMouse API (en gerelateerde timer proc) zijn verwijderd. Gebruik in plaats daarvan de Win32-API TrackMouseEvent .

  • Er is een parameter toegevoegd aan de CFolderPickerDialog constructor. (Het is een standaardparameter en is dus niet bronverbrekend.)

  • CFileStatus structuurgrootte gewijzigd: het m_attribute lidmaatschap is gewijzigd van BYTE naar DWORD (om overeen te komen met de waarde die wordt geretourneerd vanuit GetFileAttributes).

  • CRichEditCtrl en CRichEditView gebruik MSFTEDIT_CLASS (RichEdit 4.1-besturingselement) in plaats van RICHEDIT_CLASS (RichEdit 3.0-besturingselement) in Unicode-builds.

  • Verwijderd AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground omdat deze altijd WAAR is op Windows Vista, Windows 7 en Windows 8.

  • Verwijderd AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable omdat deze altijd WAAR is op Windows Vista, Windows 7 en Windows 8.

  • Verwijderd AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea. Roep de Windows-API rechtstreeks aan op Windows Vista, Windows 7 en Windows 8.

  • Verwijderd AFX_GLOBAL_DATA::DwmDefWindowProc. Roep de Windows-API rechtstreeks aan op Windows Vista, Windows 7 en Windows 8.

  • De naam AFX_GLOBAL_DATA::DwmIsCompositionEnabled is gewijzigd naar IsDwmCompositionEnabled om naamconflicten te elimineren.

  • Identificatoren gewijzigd voor een aantal interne MFC-timers en de definities zijn verplaatst naar afxres.h (identificatiereferentie AFX_TIMER_ID_*).

  • De signatuur van de methode OnExitSizeMove gewijzigd om in overeenstemming te brengen met de ON_WM_EXITSIZEMOVE macro.

    • CFrameWndEx

    • CMDIFrameWndEx

    • CPaneFrameWnd

  • De naam en handtekening van OnDWMCompositionChanged, zodat deze overeenkomen met de ON_WM_DWMCOMPOSITIONCHANGED macro:

    • CFrameWndEx

    • CMDIFrameWndEx

    • CPaneFrameWnd

  • De signatuur van de methode OnMouseLeave gewijzigd om te voldoen aan de ON_WM_MOUSELEAVE macro:

    • CMFCCaptionBar

    • CMFCColorBar

    • CMFCHeaderCtrl

    • CMFCProperySheetListBox

    • CMFCRibbonBar

    • CMFCRibbonPanelMenuBar

    • CMFCRibbonRichEditCtrl

    • CMFCSpinButtonCtrl

    • CMFCToolBar VervangDezeTekst

    • CMFCToolBarComboBoxEdit

    • CMFCToolBarEditCtrl

    • CMFCAutoHideBar

  • De signatuur van OnPowerBroadcast gewijzigd om overeen te komen met de ON_WM_POWERBROADCAST-macro.

    • CFrameWndEx

    • CMDIFrameWndEx

  • De signatuur van OnStyleChanged gewijzigd om overeen te komen met de ON_WM_STYLECHANGED macro:

    • CMFCListCtrl

    • CMFCStatusBar

  • Wijzig de naam van de interne methode FontFamalyProcFonts in FontFamilyProcFonts.

  • Talloze globale statische CString objecten verwijderd om geheugenlekken in sommige situaties te voorkomen (vervangen door #defines) en de volgende klasselidvariabelen:

    • 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

  • De signatuur van CKeyboardManager::ShowAllAccelerators is gewijzigd en de parameter voor het scheidingsteken van de accelerator is verwijderd.

  • Toegevoegd CPropertyPage::GetParentSheet, en in de CPropertyPage klasse, roep het aan in plaats van GetParent om het juiste bovenliggende bladvenster te verkrijgen, dat het ouder- of grootoudervenster van CPropertyPage kan zijn. Mogelijk moet u uw code wijzigen om aan te roepen GetParentSheet in plaats van GetParent.

  • Ongebalanceerde #pragma warning(push) in ATLBASE.H opgelost, waardoor waarschuwingen onjuist werden uitgeschakeld. Deze waarschuwingen zijn nu correct ingeschakeld na het parsen van ATLBASE.H.

  • D2D-gerelateerde methoden verplaatst van AFX_GLOBAL_DATA naar _AFX_D2D_STATE:

    • GetDirectD2dFactory

    • GetWriteFactory

    • GetWICFactory

    • InitD2D

    • ReleaseD2DRefs

    • IsD2DInitialized

    • D2D1MakeRotateMatrix

    • In plaats van bijvoorbeeld afxGlobalData.IsD2DInitialized te bellen, bel AfxGetD2DState->IsD2DInitialized.

  • Verouderde ATL*.CPP-bestanden verwijderd uit de map \atlmfc\include\.

  • De initialisatie van afxGlobalData is verplaatst naar on-demand in plaats van tijdens de CRT-initialisatie om te voldoen aan de DLLMain-vereisten.

  • De methode RemoveButtonByIndex toegevoegd aan de klasse CMFCOutlookBarPane.

  • CMFCCmdUsageCount::IsFreqeuntlyUsedCmd gecorrigeerd naar IsFrequentlyUsedCmd.

  • Verschillende exemplaren van RestoreOriginalstate naar RestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).

  • Ongebruikte methoden verwijderd uit CDockablePane: SetCaptionStyle, IsDrawCaption, IsHideDisabledButtons, , GetRecentSiblingPaneInfoen CanAdjustLayout.

  • Verwijderd statische CDockablePane lidvariabelen m_bCaptionText en m_bHideDisabledButtons.

  • Er is een onderdrukkingsmethode DeleteString toegevoegd aan CMFCFontComboBox.

  • Ongebruikte methoden verwijderd uit CPane: GetMinLength en IsLastPaneOnLastRow.

  • De naam is gewijzigd CPane::GetDockSiteRow(CDockingPanesRow *) in CPane::SetDockSiteRow.

Wijzigingen die fouten veroorzaken in Visual Studio 2010

Samensteller

  • Het auto trefwoord heeft een nieuwe standaard betekenis. Omdat het gebruik van de oude betekenis zeldzaam is, worden de meeste toepassingen niet beïnvloed door deze wijziging.

  • Het nieuwe static_assert trefwoord wordt geïntroduceerd, wat een naamconflict veroorzaakt als er al een id is door die naam in uw code.

  • Ondersteuning voor de nieuwe lambda-notatie sluit ondersteuning voor het coderen van een niet-aanhalings-GUID in een IDL-uuid-kenmerk.

  • In .NET Framework 4 wordt het concept van beschadigde status-uitzonderingen geïntroduceerd. Dit zijn uitzonderingen die een proces in een onherstelbare beschadigde status achterlaten. Standaard kunt u geen gecorrupte toestandexceptie opvangen, zelfs niet met de /EHa-compileroptie waarmee alle andere uitzonderingen worden ondervangen. Als u expliciet een beschadigde status-uitzondering wilt ondervangen, gebruikt u __try-__except-instructies. U kunt ook het kenmerk [HandledProcessCorruptedStateExceptions]toepassen om een functie in staat te stellen beschadigde statusuitzonderingen te ondervangen. Deze wijziging is voornamelijk van invloed op systeemprogrammeurs die mogelijk een beschadigde status-uitzondering moeten ondervangen. De acht uitzonderingen zijn 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. Zie de macro GetExceptionCode voor meer informatie over deze uitzonderingen.

  • De herziene /GS compileroptie beschermt tegen bufferoverschrijdingen die uitgebreider zijn dan in eerdere versies. Deze versie kan extra beveiligingscontroles in de stack invoegen die de prestaties kunnen verminderen. Gebruik het nieuwe __declspec(safebuffers) trefwoord om de compiler te instrueren geen beveiligingscontroles voor een bepaalde functie in te voegen.

  • Als u compileert met zowel de /GL compileropties (Whole Program Optimization) als /clr (Common Language Runtime Compilation), wordt de /GL optie genegeerd. Deze wijziging is aangebracht omdat de combinatie van compileropties weinig voordeel biedt. Als gevolg van deze wijziging worden de prestaties van de build verbeterd.

  • Standaard is ondersteuning voor trigraphs uitgeschakeld in Visual Studio 2010. Gebruik de /Zc:trigraphs compileroptie om trigraphs-ondersteuning in te schakelen. Een trigraph bestaat uit twee opeenvolgende vraagtekens ("??") gevolgd door een uniek derde teken. De compiler vervangt een trigraph door een bijbehorend interpunctieteken. De compiler vervangt bijvoorbeeld de ??= trigraph door het teken '#'. Gebruik trigraphs in C-bronbestanden die gebruikmaken van een tekenset die geen handige grafische weergaven voor sommige leestekens bevat.

  • De linker ondersteunt het optimaliseren voor Windows 98 niet meer. De /OPT optie (Optimalisaties) produceert een compilatietijdfout als u opgeeft /OPT:WIN98 of /OPT:NOWIN98.

  • De standaardcompileropties die zijn opgegeven door de RuntimeLibrary- en DebugInformationFormat-buildsysteem-eigenschappen zijn gewijzigd. Deze build-eigenschappen worden standaard opgegeven in projecten die zijn gemaakt door Visual C++ releases 7.0 tot en met 10.0. Als u een project migreert dat is gemaakt door Visual C++ 6.0, kunt u overwegen of u een waarde voor deze eigenschappen wilt opgeven.

  • In Visual Studio 2010, RuntimeLibrary = MultiThreaded (/MD) en DebugInformationFormat = ProgramDatabase (/Zi). In Visual C++ 9.0, RuntimeLibrary = MultiThreaded (/MT) en DebugInformationFormat = Disabled.

CLR (Common Language Runtime)

  • De Microsoft C#- en Visual Basic-compilers kunnen nu een geen primaire interop-assembly (no-PIA) produceren. Een assembly zonder PIA kan COM-typen gebruiken zonder de implementatie van de relevante primaire interop-assembly (PIA). Wanneer u no-PIA-assembly's gebruikt die worden geproduceerd door Visual C# of Visual Basic, moet u in de compilatieopdracht verwijzen naar de PIA-assembly voordat u verwijst naar een no-PIA-assembly die gebruikmaakt van de bibliotheek.

Visual Studio C++ projecten en MSBuild

  • Visual Studio C++-projecten zijn nu gebaseerd op de MSBuild-tool. Projectbestanden maken daarom gebruik van een nieuwe XML-bestandsindeling en een .vcxproj bestandsachtervoegsel. Visual Studio 2010 converteert automatisch projectbestanden van eerdere versies van Visual Studio naar de nieuwe bestandsindeling. Een bestaand project wordt beïnvloed als dit afhankelijk is van het vorige buildhulpprogramma, VCBUILD.exeof het achtervoegsel van het projectbestand, .vcproj.

  • In eerdere versies ondersteunde Visual C++ de late evaluatie van eigenschappensheets. Een bovenliggend eigenschappenvenster kan bijvoorbeeld een onderliggend eigenschappenvenster importeren, en het bovenliggende eigenschappenvenster kan een variabele gebruiken die in het onderliggende eigenschappenvenster is gedefinieerd om andere variabelen te definiëren. Uitgestelde evaluatie stelde de ouder in staat om de kindvariabele te gebruiken, zelfs voordat het kind-eigenschappenblad werd geïmporteerd. In Visual Studio 2010 kan een projectbladvariabele niet worden gebruikt voordat deze is gedefinieerd, omdat MSBuild alleen vroege evaluatie ondersteunt.

IDE

  • Het dialoogvenster voor het beëindigen van een toepassing beëindigt een toepassing niet meer. In eerdere releases, toen de abort() of terminate() functie de retailbuild van een toepassing heeft gesloten, heeft de C Run-Time-bibliotheek een bericht over het beëindigen van een toepassing weergegeven in een consolevenster of dialoogvenster. Het bericht zei gedeeltelijk: "Deze toepassing heeft de runtime gevraagd deze op een ongebruikelijke manier te beëindigen. Neem contact op met het ondersteuningsteam van de toepassing voor meer informatie. Het bericht over het beëindigen van de toepassing is redundant omdat Windows vervolgens de huidige beëindigingshandler heeft weergegeven. Dit was meestal het dialoogvenster Windows Foutrapportage (Dr. Watson) of het Foutopsporingsprogramma van Visual Studio. Vanaf Visual Studio 2010 wordt het bericht niet weergegeven in de C Run-Time-bibliotheek. Bovendien voorkomt de runtime dat de toepassing eindigt voordat een foutopsporingsprogramma wordt gestart. Dit is alleen een belangrijke wijziging als u afhankelijk bent van het vorige gedrag van het beëindigingsbericht van de toepassing.

  • Met name voor Visual Studio 2010 werkt IntelliSense niet voor C++/CLI-code of -kenmerken, zoeken naar alle verwijzingen werkt niet voor lokale variabelen en codemodel haalt geen typenamen op uit geïmporteerde assembly's of zet typen om in hun volledig gekwalificeerde namen.

Bibliotheken

  • De SafeInt-klasse is opgenomen in Visual C++ en bevindt zich niet meer in een afzonderlijke download. Dit is alleen een belangrijke wijziging als u een klasse hebt ontwikkeld met de naam 'SafeInt'.

  • Het implementatiemodel voor bibliotheken gebruikt geen manifesten meer om een bepaalde versie van een dynamische koppelingsbibliotheek te vinden. In plaats daarvan bevat de naam van elke dynamische koppelingsbibliotheek het versienummer en gebruikt u die naam om de bibliotheek te zoeken.

  • In eerdere versies van Visual Studio kunt u de runtimebibliotheken opnieuw opbouwen. Visual Studio 2010 biedt geen ondersteuning meer voor het bouwen van uw eigen kopieën van de C-runtimebibliotheekbestanden.

Standaardbibliotheek

  • De <iterator> header wordt niet meer automatisch opgenomen door veel andere headerbestanden. Neem in plaats daarvan die header expliciet op als u ondersteuning nodig hebt voor de zelfstandige iterators die zijn gedefinieerd in de header. Een bestaand project wordt beïnvloed als dit afhankelijk is van het vorige buildhulpprogramma, VCBUILD.exeof het achtervoegsel van het projectbestand, .vcproj.iterator.

  • In de <algorithm> koptekst worden de checked_* en unchecked_* functies verwijderd. En in de <iterator>> koptekst wordt de checked_iterator klasse verwijderd en is de unchecked_array_iterator klasse toegevoegd.

  • De CComPtr::CComPtr(int) constructor wordt verwijderd. Met deze constructor kon een CComPtr object worden samengesteld uit de NULL macro, maar dit was onnodig en stond onzinnige constructies toe van niet-nul-gelijke gehele getallen.

    Een CComPtr kan nog steeds worden samengesteld op basis van NULL, wat is gedefinieerd als 0, maar mislukt als deze is samengesteld op basis van een geheel getal dat niet letterlijk 0 is. Gebruik in plaats daarvan nullptr.

  • De volgende ctype lidfuncties zijn verwijderd: ctype::_Do_narrow_s, ctype::_Do_widen_s, ctype::_narrow_s, . ctype::_widen_s Als een toepassing een van deze lidfuncties gebruikt, moet u deze vervangen door de bijbehorende niet-beveiligde versie: ctype::do_narrow, ctype::do_widen, ctype::narrow, . ctype::widen

CRT-, MFC- en ATL-bibliotheken

  • Ondersteuning is verwijderd voor gebruikers om de CRT-, MFC- en ATL-bibliotheken te bouwen. Er is bijvoorbeeld geen geschikt NMAKE-bestand opgegeven. Gebruikers hebben echter nog steeds toegang tot de broncode voor deze bibliotheken. En een document dat de MSBuild-opties beschrijft die Microsoft gebruikt om deze bibliotheken te bouwen, wordt waarschijnlijk gepost in een Visual C++-teamblog.

  • MFC-ondersteuning voor IA64 is verwijderd. Er wordt echter nog wel ondersteuning geboden voor de CRT en ATL op IA64.

  • Ordinals worden niet meer opnieuw gebruikt in MFC moduledefinitiebestanden (.def). Deze wijziging betekent dat de rangnummers niet zullen verschillen tussen de kleinere versies en dat de binaire compatibiliteit voor servicepacks en snelle probleemoplossingsreleases wordt verbeterd.

  • Er is een nieuwe virtuele functie toegevoegd aan de CDocTemplate klasse. Deze nieuwe virtuele functie is CDocTemplate Class. De vorige versie van OpenDocumentFile had twee parameters. De nieuwe versie heeft drie parameters. Ter ondersteuning van de manager voor opnieuw opstarten moet elke klasse die is afgeleid van CDocTemplate , de versie met drie parameters implementeren. De nieuwe parameter is bAddToMRU.

Macro's en omgevingsvariabelen

  • De omgevingsvariabele __MSVCRT_HEAP_SELECT wordt niet meer ondersteund. Deze omgevingsvariabele wordt verwijderd en er is geen vervanging.

Microsoft Macro Assembler-referentie

  • Verschillende instructies zijn verwijderd uit de Microsoft Macro Assemblyer Reference Compiler. De verwijderde instructies zijn .186, .286, .286P, .287, .8086, .8087, en .NO87.

Wijzigingen die fouten veroorzaken in Visual Studio 2008

Samensteller

  • De Platforms Windows 95, Windows 98, Windows ME en Windows NT worden niet meer ondersteund. Deze besturingssystemen zijn verwijderd uit de lijst met doelplatforms.

  • De compiler ondersteunt niet langer meerdere kenmerken die rechtstreeks aan ATL Server zijn gekoppeld. De volgende kenmerken worden niet meer ondersteund:

    • perf_counter

    • perf_object

    • perfmon

    • verzoekafhandelaar

    • soap_verwerker

    • soap_header

    • soap_methode

    • tag_name

Visual Studio C++ projecten

  • Wanneer u projecten bijwerkt uit eerdere versies van Visual Studio, moet u mogelijk winver en _WIN32_WINNT macro's wijzigen, zodat ze groter zijn dan of gelijk zijn aan 0x0500.

  • Vanaf Visual Studio 2008 heeft de nieuwe projectwizard geen optie om een C++ SQL Server-project te maken. SQL Server-projecten die zijn gemaakt met behulp van een eerdere versie van Visual Studio, worden nog steeds correct gecompileerd en werken.

  • Het Windows API-headerbestand Winable.h is verwijderd. Neem in plaats daarvan Winuser.h op.

  • De Windows API-bibliotheek Rpcndr.lib is verwijderd. Koppel in plaats daarvan aan rpcrt4.lib.

CRT

  • Ondersteuning voor Windows 95, Windows 98, Windows Millennium Edition en Windows NT 4.0 is verwijderd.

  • De volgende globale variabelen zijn verwijderd:

    • _osplatform

    • _osver

    • _winmajor

    • _winminor

    • _winver

  • De volgende functies zijn verwijderd. Gebruik de Windows API-functies GetVersion of GetVersionEx in plaats daarvan:

    • _get_osplatform

    • _get_osver

    • _get_winmajor

    • _get_winminor

    • _get_winver

  • De syntaxis voor SAL-aantekeningen is gewijzigd. Zie SAL-aantekeningen voor meer informatie.

  • Het IEEE-filter ondersteunt nu de SSE 4.1-instructieset. Zie _fpieee_flt voor meer informatie.

  • De C Run-Time Bibliotheken die worden verzonden met Visual Studio zijn niet langer afhankelijk van het systeem-DLL-msvcrt.dll.

Standaardbibliotheek

  • Ondersteuning voor Windows 95, Windows 98, Windows Millennium Edition en Windows NT 4.0 is verwijderd.

  • Bij het compileren in de foutopsporingsmodus met _HAS_ITERATOR_DEBUGGING gedefinieerd (vervangen door _ITERATOR_DEBUG_LEVEL na Visual Studio 2010), zal een toepassing nu een foutmelding geven wanneer een iterator probeert verder of terug te bewegen voorbij de grenzen van de onderliggende container.

  • De lidvariabele c van de stackklasse wordt nu beveiligd gedeclareerd. Voorheen werd deze lidvariabele openbaar gedeclareerd.

  • Het gedrag van money_get::do_get is veranderd. Voorheen, wanneer een geldbedrag met meer breukcijfers dan werd gevraagd door frac_digits werd geparsed, consumeerde do_get ze allemaal. Nu stopt do_get u met parseren nadat u maximaal frac_digits tekens hebt gebruikt.

ATL

  • ATL kan niet worden gebouwd zonder een afhankelijkheid van CRT. In eerdere versies van Visual Studio kunt u #define ATL_MIN_CRT gebruiken om een ATL-project minimaal afhankelijk te maken van CRT. In Visual Studio 2008 zijn alle ATL-projecten minimaal afhankelijk van CRT, ongeacht of ATL_MIN_CRT is gedefinieerd.

  • De ATL Server-codebase is uitgebracht als een gedeeld bronproject op CodePlex en is niet geïnstalleerd als onderdeel van Visual Studio. Gegevenscoderings- en decoderingsklassen van atlenc.h en hulpprogrammafuncties en -klassen van atlutil.h en atlpath.h zijn bewaard en maken nu deel uit van de ATL-bibliotheek. Verschillende bestanden die zijn gekoppeld aan ATL Server maken geen deel meer uit van Visual Studio.

  • Sommige functies zijn niet meer opgenomen in het DLL-bestand. Ze bevinden zich nog steeds in de importbibliotheek. Dit heeft geen invloed op code die de functies statisch gebruikt. Dit is alleen van invloed op de code die deze functies dynamisch gebruikt.

  • De macro's PROP_ENTRY en PROP_ENTRY_EX zijn om veiligheidsredenen afgeschaft en vervangen door de macro's PROP_ENTRY_TYPE en PROP_ENTRY_TYPE_EX.

Gedeelde klassen ATL/MFC

  • ATL kan niet worden gebouwd zonder een afhankelijkheid van CRT. In eerdere versies van Visual Studio kon u een #define ATL_MIN_CRT ATL-project minimaal afhankelijk maken van CRT. In Visual Studio 2008 zijn alle ATL-projecten minimaal afhankelijk van CRT, ongeacht of ATL_MIN_CRT is gedefinieerd.

  • De ATL Server-codebase is uitgebracht als een gedeeld bronproject op CodePlex en is niet geïnstalleerd als onderdeel van Visual Studio. Gegevenscoderings- en decoderingsklassen van atlenc.h en hulpprogrammafuncties en -klassen van atlutil.h en atlpath.h zijn bewaard en maken nu deel uit van de ATL-bibliotheek. Verschillende bestanden die zijn gekoppeld aan ATL Server maken geen deel meer uit van Visual Studio.

  • Sommige functies zijn niet meer opgenomen in het DLL-bestand. Ze bevinden zich nog steeds in de importbibliotheek. Dit heeft geen invloed op code die de functies statisch gebruikt. Dit is alleen van invloed op de code die deze functies dynamisch gebruikt.

MFC

  • CTime Klasse: De CTime klasse accepteert nu datums vanaf 1-1-1900 C.E. in plaats van 1-1-1970 C.E.

  • Tabvolgorde van besturingselementen in MFC-dialoogvensters: De juiste tabvolgorde van meerdere besturingselementen in een MFC-dialoogvenster wordt gestoord als een MFC ActiveX-besturingselement wordt ingevoegd in de tabvolgorde. Deze wijziging corrigeert dat probleem.

    Maak bijvoorbeeld een MFC-dialoogvenstertoepassing met een ActiveX-besturingselement en verschillende bewerkingselementen. Plaats het ActiveX-besturingselement in het midden van de tabvolgorde van de besturingselementen voor bewerken. Start de toepassing, klik op een besturingselement bewerken waarvan de tabvolgorde zich na het ActiveX-besturingselement bevindt en vervolgens op tab. Vóór deze wijziging is de focus naar het besturingselement bewerken gegaan na het ActiveX-besturingselement in plaats van het volgende bewerkingsbesturingselement in de tabvolgorde.

  • CFileDialog Klasse: Aangepaste sjablonen voor de CFileDialog klasse kunnen niet automatisch worden overgezet naar Windows Vista. Ze zijn nog steeds bruikbaar, maar hebben niet de extra functionaliteit of het uiterlijk van dialoogvensters in windows Vista-stijl.

  • CWnd Klasse en CFrameWnd klasse: de CWnd::GetMenuBarInfo methode is verwijderd.

    De CFrameWnd::GetMenuBarInfo methode is nu een niet-virtuele methode. Zie de functie GetMenuBarInfo in de Windows SDK voor meer informatie.

  • MFC ISAPI-ondersteuning: MFC biedt geen ondersteuning meer voor het bouwen van toepassingen met de ISAPI (Internet Server Application Programming Interface). Als u een ISAPI-toepassing wilt bouwen, roept u de ISAPI-extensies rechtstreeks aan.

  • Afgeschafte ANSI-API's: de ANSI-versies van verschillende MFC-methoden zijn afgeschaft. Gebruik de Unicode-versies van deze methoden in uw toekomstige toepassingen. Voor meer informatie, zie Buildvereisten voor algemene besturingselementen voor Windows Vista.

Wijzigingen die fouten veroorzaken in Visual Studio 2005

CRT

  • Veel functies zijn afgeschaft. Zie verouderde CRT-functies.

  • Veel functies valideren nu hun parameters, waardoor de uitvoering wordt gestopt als er ongeldige parameters zijn opgegeven. Deze validatie kan code verbreken die ongeldige parameters doorgeeft en afhankelijk is van de functie die deze negeert of alleen een foutcode retourneert. Zie Parametervalidatie.

  • De waarde van de bestandsdescriptor -2 wordt nu gebruikt om aan te geven dat stdout en stderr niet beschikbaar zijn voor uitvoer, bijvoorbeeld in een Windows-toepassing die geen consolevenster heeft. De vorige gebruikte waarde was -1. Zie _fileno voor meer informatie.

  • De CRT-bibliotheken met één thread (libc.lib en libcd.lib) zijn verwijderd. Gebruik de CRT-bibliotheken met meerdere threads. De /ML compilervlag wordt niet meer ondersteund. Niet-vergrendelingsversies van sommige functies zijn toegevoegd in gevallen waarin het prestatieverschil tussen de multithreaded-code en de code met één thread mogelijk aanzienlijk is.

  • De overbelasting van pow, dubbele pow (int, int), werd verwijderd om beter te voldoen aan de norm.

  • De %n-indelingsaanduiding wordt standaard niet meer ondersteund in een van de printf-functies, omdat deze inherent onveilig is. Als er %n wordt aangetroffen, is het standaardgedrag het aanroepen van de ongeldige parameterhandler. Als u %n-ondersteuning wilt inschakelen, gebruikt u _set_printf_count_output (zie ook _get_printf_count_output).

  • sprintf drukt nu het negatieve teken van een getekende nul af.

  • swprintf is gewijzigd om te voldoen aan de norm; hiervoor is nu een grootteparameter vereist. De vorm van swprintf zonder een grootteparameter is afgeschaft.

  • _set_security_error_handler is verwijderd. Verwijder alle aanroepen naar die functie; de standaardhandler is een veel veiligere manier om beveiligingsfouten op te lossen.

  • time_t is nu een 64-bits waarde (tenzij _USE_32BIT_TIME_T is gedefinieerd).

  • De _spawn- en _wspawn-functies laten errno nu ongewijzigd bij succes, zoals opgegeven door de C-standaard.

  • RTC maakt nu standaard gebruik van brede tekens.

  • Ondersteuningsfuncties voor zwevendekommaregelwoorden zijn verouderd voor toepassingen gecompileerd met /CLR of /CLR:PURE. De betrokken functies zijn _clear87, , _clearfp, _control87, _controlfp, _fpreset, , , _status87. _statusfp U kunt de afschaffingswaarschuwing uitschakelen door _CRT_MANAGED_FP_NO_DEPRECATE te definiëren, maar het gebruik van deze functies in beheerde code is onvoorspelbaar en niet ondersteund.

  • Sommige functies retourneren nu const pointers. Het oude, niet-const gedrag kan opnieuw worden gereactiveerd door _CONST_RETURN te definiëren. De betrokken functies zijn

    • memchr, wmemchr

    • strchr, wcschr, _mbschr, _mbschr_l

    • strpbrk, wcspbrk, _mbspbrk, _mbspbrk_l

    • strrchr, wcsrchr, _mbsrchr, _mbsrchr_l

    • strstr, wcsstr, _mbsstr, _mbsstr_l

  • Wanneer u een koppeling maakt met Setargv.obj of Wsetargv.obj, is het niet meer mogelijk om de uitbreiding van een jokerteken op de opdrachtregel te onderdrukken door het tussen dubbele aanhalingstekens te plaatsen. Zie Argumenten voor jokertekens uitvouwen voor meer informatie.

Standaardbibliotheek (2005)

  • De uitzonderingsklasse (in de <exception> header) is verplaatst naar de std naamruimte. In eerdere versies bevindt deze klasse zich in de globale naamruimte. Als u eventuele fouten wilt oplossen die aangeven dat de uitzonderingsklasse niet kan worden gevonden, voegt u de volgende using-instructie toe aan uw code: using namespace std;

  • Wanneer u aanroept valarray::resize(), gaat de inhoud van de valarray inhoud verloren en wordt deze vervangen door standaardwaarden. De resize() methode is bedoeld om de valarray methode opnieuw te initialiseren in plaats van het dynamisch te laten groeien als een vector.

  • Fouten opsporen in iterators: toepassingen die zijn gebouwd met een foutopsporingsversie van de C-Runtime-bibliotheek en die iterators onjuist gebruiken, kunnen tijdens runtime asserties zien. Als u deze asserties wilt uitschakelen, moet u _HAS_ITERATOR_DEBUGGING definiëren (vervangen door _ITERATOR_DEBUG_LEVEL Visual Studio 2010) tot 0. Zie Ondersteuning voor foutopsporing voor Iterator voor meer informatie

Visual C++ .NET 2003 Belangrijke wijzigingen

Samensteller

  • Haakjes sluiten is nu vereist voor de gedefinieerde preprocessorrichtlijn (C2004).

  • Expliciete specialisaties vinden geen sjabloonparameters meer van de primaire sjabloon (compilerfout C2146).

  • Een beveiligd lid (n) kan alleen worden geopend via een lidfunctie van een klasse (B) die overgaat van de klasse (A) waarvan het lid (n) lid is (compilerfout C2247).

  • Verbeterde toegankelijkheidscontroles in compiler detecteren nu ontoegankelijke basisklassen (compilerfout C2248).

  • Een uitzondering kan niet worden opgevangen als destructor en/of kopieerconstructor niet toegankelijk is (C2316).

  • Standaardargumenten voor aanwijzers naar functies zijn niet meer toegestaan (compilerfout C2383).

  • Een statisch gegevenslid kan niet worden geïnitialiseerd via afgeleide klasse (compilerfout C2477).

  • De initialisatie van een is typedef niet toegestaan volgens de standaard en genereert nu een compilerfout (compilerfout C2513).

  • bool is nu het juiste type (compilerfout C2632).

  • Een UDC kan nu dubbelzinnigheid maken met overbelaste operators (C2666).

  • Meer expressies worden nu beschouwd als geldige null-aanwijzerconstanten (compilerfout C2668).

  • sjabloon<> is nu vereist op plaatsen waar de compiler dit eerder zou impliceren (compilerfout C2768).

  • De expliciete specialisatie van een lidfunctie buiten de klasse is niet geldig als de functie al expliciet is gespecialiseerd via een sjabloonklassespecialisatie (compilerfout C2910).

  • Sjabloonparameters die niet van het type drijvende komma zijn, zijn niet meer toegestaan (compilerfout C2993).

  • Klassesjablonen zijn niet toegestaan als sjabloontypeargumenten (C3206).

  • Namen van friend-functies worden niet langer geïntroduceerd in de omvattende naamruimte (compilerfout C3767).

  • De compiler accepteert geen extra komma's meer in een macro (C4002).

  • Een object van het POD-type dat is samengesteld met een initialisatiefunctie van het formulier () wordt standaard geïnitialiseerd (C4345).

  • typenaam is nu vereist als een afhankelijke naam moet worden behandeld als een type (compilerwaarschuwing (niveau 1) C4346).

  • Functies die onjuist als sjabloonspecialisaties werden beschouwd, worden niet langer als zodanig beschouwd (C4347).

  • Statische gegevensleden kunnen niet worden geïnitialiseerd via afgeleide klasse (C4356).

  • Een specialisatie van een klassesjabloon moet worden gedefinieerd voordat deze wordt gebruikt in een retourtype (Compilerwaarschuwing (niveau 3) C4686).

  • De compiler rapporteert nu onbereikbare code (C4702).

Zie ook

Wat is er nieuw voor Visual C++ in Visual Studio