Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of mappen te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen om mappen te wijzigen.
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
/NODEFAULTLIBlinkeroptie 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.liben vcruntimedversie.dll. De versie in Visual Studio 2015 en Visual Studio 2017 is 140. Zie CRT-Bibliotheekfuncties.
<locale.h>
localeconvDe
localeconvfunctie die is gedeclareerd in locale.h, werkt nu correct wanneer landinstellingen per thread zijn ingeschakeld. In eerdere versies van de bibliotheek retourneert deze functie delconvgegevens voor de globale landinstelling, niet de landinstelling van de thread.Als u landinstellingen per thread gebruikt, moet u het gebruik van
localeconvcontroleren. Als uw code ervan uitgaat dat delconvgeretourneerde 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)enfloat 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) -
floatenlong doubleversies van functies voor drijvende-kommaacos,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, entrunc
Als u code hebt die gebruikmaakt van
absmet een drijvende-komma-type dat alleen de<math.h>header bevat, zijn de drijvende-komma-versies niet meer beschikbaar. De aanroep wordt nu omgezet inabs(int), zelfs met een kommagetalarugment, wat de fout veroorzaakt.warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of dataDe oplossing voor deze waarschuwing is om de aanroep naar
abste vervangen door een zwevendekommaversie vanabs, zoalsfabsvoor een dubbel argument offabsfvoor een floatargument, of inclusief de<cmath>header enabste 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>
newendeleteIn 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:pureoptie 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>
_beginthreaden_beginthreadexDe
_beginthreaden_beginthreadexfuncties 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_starten verwijzingstypenBij het compileren van C++-code controleert
va_startnu 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
printffuncties enscanffuncties 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 voegenlegacy_stdio_definitions.libaan 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.libaan 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.exede 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.libgets 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 (
INFin plaats vaninf), zoals vereist.De scanf-functies zijn gewijzigd om deze nieuwe tekenreeksen te parseren, zodat deze tekenreeksen nu via
printfenscanfheen 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:
1208925819614629200000000Nieuwe uitvoer:
1208925819614629174706176De 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
printffuncties 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
printffuncties 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
printfenscanffuncties 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
fopenfamilie van functies op de achtergrond enkele ongeldige modustekenreeksen geaccepteerd, zoalsr+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
snprintfofvsnprintfin gebruikerscode.tmpnam genereert bruikbare bestandsnamen
In eerdere versies genereerden de
tmpnamentmpnam_sfuncties 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
strtofenwcstofslaagden er niet in omerrnoop ERANGE in te stellen wanneer de waarde niet als float kon worden weergegeven. Deze fout was specifiek voor deze twee functies; destrtod,wcstod,strtold, enwcstoldfuncties 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_heapusedfuncties zijn verwijderd. Deze functies zijn niet-functioneel sinds de CRT is bijgewerkt om de Windows-heap te gebruiken.smallheap
De
smallheapkoppelingsoptie is verwijderd. Zie Koppelingsopties._Stat
De
_stat-functies maken gebruik vanCreateFilein Visual Studio 2015, in plaats vanFindFirstFilezoals in Visual Studio 2013 en eerder. Dit betekent dat_statop 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 meterrnoingesteld opENOENT.
<string.h>
wcstokDe handtekening van de
wcstokfunctie 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 handtekeningwchar_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
_wcstokfunctie toegevoegd met de oude handtekening om de overdracht te vereenvoudigen. Bij het compileren van C++-code is er ook een inline overload vanwcstokdie de oude signatuur heeft. Deze overload is als verouderd gemarkeerd. In C-code kunt u define_CRT_NON_CONFORMING_WCSTOK definiëren zodat_wcstokwordt gebruikt in plaats vanwcstok.
<time.h>
klok
In eerdere versies is de
clockfunctie geïmplementeerd met behulp van de Windows-APIGetSystemTimeAsFileTime. Met deze implementatie was de klokfunctie gevoelig voor de systeemtijd en was dus niet noodzakelijkerwijs monotone. De klokfunctie is heringevoerd aan de hand vanQueryPerformanceCounteren is nu monotoon.fstat en _utime
In eerdere versies verwerken de
_stat,fstaten_utimefuncties 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
_statfunctiesfamilie, maar de vergelijkbare problemen in defstatfuncties en_utimefamilies van functies zijn niet opgelost. Deze gedeeltelijke oplossing heeft geleid tot problemen vanwege de inconsistentie tussen de functies. Defstatfuncties en_utimefamilies van functies zijn nu opgelost, dus al deze functies verwerken nu zomertijd correct en consistent.asctime
In eerdere versies zou de functie
asctimedagen 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 inFri Jun 6 08:00:00 2014. Dit probleem is opgelost.strftime en wcsftime
De
strftimeenwcsftimefuncties 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 doorasctime. In eerdere versies werd de %c-notatieaanduiding onjuist gebruikt om tijden te formatteren met eenMM/DD/YY HH:MM:SSrepresentatie. Dit probleem is opgelost.timespec en TIME_UTC
De
<time.h>header definieert nu hettimespectype en detimespec_getfunctie van de C11 Standard. Daarnaast is de TIME_UTC macro, voor gebruik met detimespec_getfunctie, 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 allestd::arrayop 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 vansteady_clockis veranderd om te voldoen aan de C++-standaardvereisten voor stabielheid en monotoniteit.steady_clockis nu gebaseerd opQueryPerformanceCounterenhigh_resolution_clockis nu een typedef voorsteady_clock. Als gevolg hiervan is Visual Studiosteady_clock::time_pointnu een typedef voorchrono::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) constconst-elementen
De C++-standaard heeft altijd verboden containers van const-elementen (zoals
vector<const T>ofset<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 vanallocate, 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) consttypeeigenschappen
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::anyenlaunch::syncbeleidsregels zijn verwijderd. Gebruik in plaats daarvanlaunch::anyvoorlaunch:async | launch:deferred. Voorlaunch::sync, gebruiklaunch::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
#undefgebruikt om de Yield-macro ongedaan te maken en zo conflicten te vermijden tussen de Yield-macro die is gedefinieerd in Windows.h en deconcurrency::Context::Yield-functie. Dit#undefis 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 deYieldExecutionfunctie aan te roepen of deYieldfunctienaam 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 releaseDeze 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
/Zaoptie 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/Zaoptie 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 }/ZgcompileroptieDe
/Zgcompileroptie (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
mutableaanduiding 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 demutableaanduiding 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 classVerwijder het redundante
mutabletrefwoord om de fout op te lossen.char_16_t en char32_t
U kunt niet langer
char16_tofchar32_tals aliassen in eentypedefgebruiken, omdat deze typen nu als standaard worden beschouwd. Het was gebruikelijk voor gebruikers en bibliotheekauteurs omchar16_tenchar32_trespectievelijk als aliassen vanuint16_tenuint32_tte 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
typedefdeclaraties 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 declarationsAls 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
publicis en nietexplicitgemarkeerd 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
catchin 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
_xis, 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
deleteoperator 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 globaledeleteoperator die een grootteparameter gebruikt. De belangrijke wijziging is dat als u eerder een operatordeletemet 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 (globaledeleteoperator). 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
deleteoperator. Overweeg of u een ander type kunt gebruiken dansize_tvoor placement new endeleteoperatoren. Het type van desize_ttypedefis afhankelijk van de compiler; het is eentypedefvoorunsigned intin 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
deletegebruik dit type als het tweede argument in plaats vansize_t. U moet ook de aanroepen van 'placement new' bijwerken om het nieuwe type door te geven (bijvoorbeeld doorstatic_cast<my_type>te gebruiken om vanuit de integerwaarde te converteren) en de definitie vannewendeleteom terug te casten naar het integertype. U hoeft hiervoor geen gebruik te makenenum. Een klassetype met eensize_tlid 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
deletegebruiken 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 typeAls 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; // C2280Met 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>' hereU 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 calledAls 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
Dnog 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
BenDnaar 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(){} // C4430Als u de fout wilt oplossen, voegt u het retourtype toe:
extern "C" int __cdecl main(){} // OKtypename 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
typenameuit 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_assertcode altijd mislukt:template <size_t some_value> struct S1 { static_assert(false, "default not valid"); // always invoked }; //other partial specializations hereOm 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 hereRegels 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 identifierU 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 eenusingdeclaratie op te lossen.Dit patroon gebeurt vaak met ComPtr en andere typen in de
Microsoft::WRLnaamruimte.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 vanhzodat 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
MACROvoorbeeld 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.alignofis nu een trefwoordDe 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{}constexpris nu een trefwoordDe 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); //C2280Als 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}; //OKConversie 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
S2inS: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::movein 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
S2uit 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
0of gebruikt u in plaats daarvannullptr, 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
Ahet volgende om het probleem op te lossen:#define A intExtra 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 eentypedef.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_assertaanwijzersDte vergelijken met enB2:static_assert(std::is_convertible<D*, B2*>::value, "fail");__declspec(novtable) declaraties moeten consistent zijn
__declspecdeclaraties 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 virtualbasisklassen 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 functionVoorbeeld (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
newofdeleteoperator 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 C2323Voorbeeld (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
newbeschouwd 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/unionVoorbeeld (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
typenametoe 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 specifierVoorbeeld (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
switchinstructies 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' labelswarning C4061: enumerator 'bit1' in switch of enum 'flags' is not explicitly handled by a case labelwarning C4062: enumerator 'bit1' in switch of enum 'flags' is not handledwarning 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' labelswarning 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 givenVoorbeeld 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
#includerichtlijnen. 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 C4464Voorbeeld (na)
#include "C4426.h" // add absolute path to 'headers\' to your project's include directoriesBovendien, 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 C4426Voorbeeld (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 fileVoorbeeld (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
#includevolgorde. 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.hVoorbeeld (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 warningnu de status robuuster bij , met name gerelateerd aan#pragma warningstatuswijzigingen 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 codeIn 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
decltypede 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
decltypeexpressie 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 hettypename-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 typeerror 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> ())); };volatilelidvariabelen voorkomen impliciet gedefinieerde constructors en toewijzingsoperatorenIn eerdere versies van de compiler stond een klasse met
volatilelidvariabelen 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 metvolatilelidvariabelen 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 functionVoorbeeld (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 C2280Voorbeeld (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 C2280Statische 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 {} // C2511Voorbeeld (na)
struct A { static void func(); }; void A::func() {} // removed constForward-declaratie van enum is niet toegestaan in WinRT-code (alleen van invloed op
/ZW)Met code die is gecompileerd voor Windows Runtime (WinRT) kunnen
enumtypen niet vooruit worden gedeclareerd, net zoals wanneer beheerde C++-code voor het .Net Framework wordt gecompileerd met de/clrcompilerswitch. 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 allowederror C3197: 'public': can only be used in definitionsVoorbeeld (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 inlineVoorbeeld (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_convertabletype-eigenschap is de zelftoewijzing van een klassetype niet correct gedetecteerd wanneer de kopieerconstructor wordt verwijderd of privé is. Nu wordtstd::is_convertable<>::valuecorrect ingesteld opfalsewanneer 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<>::valueonjuist was ingesteld alstrue. Nu isstd::is_convertable<>::valuecorrect ingesteld opfalse, 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 deprecatedAls u ATL-code wilt blijven gebruiken totdat de ondersteuning van de compiler wordt verwijderd, kunt u deze waarschuwing uitschakelen door de
/Wv:18argumenten of/wd:4467opdrachtregelargumenten 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
#includeinstructies in bronbestanden tussen-Ycen-Yucompilaties 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#includeinstructies 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 positionVoorbeeld (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-Ycen-Yucompilaties 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 positionVoorbeeld (vóór)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h Z.cppVoorbeeld (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
virtualaanroep 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 vanS2::fbevat.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
friendfunctie: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
xom te worden omgezet in het typeint:auto x = {0}; int y = x;Deze code wordt nu omgezet
xin een typestd::initializer_list<int>en veroorzaakt een fout op de volgende regel die probeert toe te wijzenxaan het typeint. (Er is standaard geen conversie.) Als u deze code wilt corrigeren, gebruiktintu om het volgende te vervangenauto: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}; // errorAls 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
E1in-expressieE1::bomgezet in::E1het globale bereik. In Visual Studio 2013 wordtE1in de expressieE1::bomgezet in de definitietypedef E2inmain()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
virtualfunctie heeft maar geen basisklasse heeft die eenvirtualfunctie heeft, wordt met het objectmodel van de compiler een aanwijzer naar eenvirtualfunctietabel 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 eenvirtualfunctie 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
/W3compileroptie 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 zeggenallocator_traits<A>::rebind_alloc<U>. Hoewelratio_add<R1, R2>::typeniet meer nodig is en we u nu aanraden omratio_add<R1, R2>te zeggen, zal de eerdere nog steeds worden gecompileerd omdatratio<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 beltstd::min()ofstd::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 zeggenstd::future_status. De meeste code wordt echter niet beïnvloed, bijvoorbeeldstd::future_status::readynog 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> spzowelstatic_cast<bool>(sp)alsbool b(sp)geldig, en booleaanse testbare 'contextuele conversies' aan bool, bijvoorbeeldif (sp), ,!spwatsp &&dan ook.explicit operator bool()verbiedt echter impliciete conversies naar bool, dus je kunt niet zeggenbool b = sp;en met een bool-retvaltyp kun je niet zeggenreturn 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()encref()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 datcommon_type<int, int>::typeint&&retourneert. Daarom implementeert de compiler de voorgestelde oplossing voor Bibliotheekwerk groepskwestie 2141, zodatcommon_type<int, int="">::typeintretourneert.Als neveneffect van deze wijziging werkt de identiteitscase niet meer (
common_type<T>resulteert niet altijd in typeT). 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::identitydie 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::GetConnectwordt 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 deCDatabase::Dumpfunctie te gebruiken.CWnd::OnPowerBroadcastDe 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::OnDisplayChangegewijzigd in (UINT, int, int) in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_DISPLAYCHANGE macro te gebruiken is in de berichtenmap.CFrameWnd::OnDDEInitiategewijzigd in (CWnd*, UINT, UNIT) in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_DDE_INITIATE macro kan worden gebruikt in de berichtenkaart.CFrameWnd::OnDDEExecutegewijzigd in (CWnd*, HANDLE) in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_DDE_EXECUTE macro kan worden gebruikt in de berichtenmap.CFrameWnd::OnDDETerminategewijzigd 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::OnCutgewijzigd in geen parameters in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_CUT macro kan worden gebruikt in de berichtkaart.CMFCMaskedEdit::OnCleargewijzigd naar geen parameters in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_CLEAR macro kan worden gebruikt in de berichtmap.CMFCMaskedEdit::OnPastegewijzigd naar geen parameters in plaats van (WPARAM, LPARAM), zodat de nieuwe ON_WM_PASTE macro in de berichtenmap kan worden gebruikt.
#ifdefinstructies in de MFC-headerbestanden worden verwijderd. Talrijke#ifdefinstructies 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
CTraceCategoryconstructor 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
/Ylcompileroptie 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 hetenumklassetrefwoord 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
/GSopdrachtregeloptie 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 terminateDe 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:IA32compilervlag 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
/HIGHENTROPYVAis 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
/HIGHENTROPYVAook voor beheerde builds. In dit geval is de/HIGHENTROPYVAswitchstandaardinstelling 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 inmake_pair<int, int>(x, y), wordt doorgaans niet gecompileerd in Visual C++ in Visual Studio 2012. De oplossing is altijd aanroepenmake_pair()zonder expliciete sjabloonargumenten, zoals inmake_pair(x, y). Het gebruiken van expliciete sjabloonargumenten ondermijnt het doel van de functie. Gebruikpairin plaats vanmake_pairals u nauwkeurige controle over het resulterende type nodig hebt, zoals inpair<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 naarpair<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 vanfunc(const pair<int, int>&)enfunc(const pair<string, string>&), en het aanroepen vanfunc()metpair<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 gevenmake_pair(static_cast<B>(a), x)aan een functie die verwachtpair<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
newtoegestaan, 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<=()enoperator>=()waren eerder beschikbaar voor destd::unordered_mapenstdext::hash_mapfamilies van containers, hoewel hun implementaties niet nuttig waren. Deze niet-standaardoperators zijn verwijderd in Visual C++ in Visual Studio 2012. Daarnaast is de implementatie vanoperator==()enoperator!=()voor destd::unordered_mapfamilie uitgebreid om destdext::hash_mapfamilie te dekken. (U wordt aangeraden het gebruik van destdext::hash_mapfamilie in nieuwe code te vermijden.)C++11 22.4.1.4 [locale.codecvt] geeft aan dat
codecvt::length()encodecvt::do_length()wijzigbarestateT&-parameters moeten aannemen, maar Visual Studio 2010 namconst stateT&. De C++-compiler in Visual Studio 2012 accepteertstateT&zoals voorgeschreven door de standaard. Dit verschil is belangrijk voor iedereen die de virtuele functiedo_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
threadlocaleinfostructstruct 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::RemoveFromDefaultPaneDividierveranderd naarCDockablePane::RemoveFromDefaultPaneDivider.De handtekening van
CFileDialog::SetDefExtis gewijzigd naar het gebruik van LPCTSTR; hierdoor worden Unicode-builds beïnvloed.Verouderde ATL-traceringscategorieën zijn verwijderd.
De signatuur van
CBasePane::MoveWindowgewijzigd zodat deze eenconst CRectaccepteert.De handtekening van
CMFCEditBrowseCtrl::EnableBrowseButtonis veranderd.Verwijderd
m_fntTabsenm_fntTabsBoldvanCMFCBaseTabCtrl.Er is een parameter toegevoegd aan de
CMFCRibbonStatusBarPaneconstructors. (Het is een standaardparameter en is dus niet bronverbrekend.)Er is een parameter toegevoegd aan de
CMFCRibbonCommandsListBoxconstructor. (Het is een standaardparameter en is dus niet bronverbrekend.)De
AFXTrackMouseAPI (en gerelateerde timer proc) zijn verwijderd. Gebruik in plaats daarvan de Win32-APITrackMouseEvent.Er is een parameter toegevoegd aan de
CFolderPickerDialogconstructor. (Het is een standaardparameter en is dus niet bronverbrekend.)CFileStatusstructuurgrootte gewijzigd: hetm_attributelidmaatschap is gewijzigd van BYTE naar DWORD (om overeen te komen met de waarde die wordt geretourneerd vanuitGetFileAttributes).CRichEditCtrlenCRichEditViewgebruik MSFTEDIT_CLASS (RichEdit 4.1-besturingselement) in plaats van RICHEDIT_CLASS (RichEdit 3.0-besturingselement) in Unicode-builds.Verwijderd
AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackgroundomdat deze altijd WAAR is op Windows Vista, Windows 7 en Windows 8.Verwijderd
AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailableomdat 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::DwmIsCompositionEnabledis gewijzigd naarIsDwmCompositionEnabledom 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
OnExitSizeMovegewijzigd om in overeenstemming te brengen met de ON_WM_EXITSIZEMOVE macro.CFrameWndExCMDIFrameWndExCPaneFrameWnd
De naam en handtekening van
OnDWMCompositionChanged, zodat deze overeenkomen met de ON_WM_DWMCOMPOSITIONCHANGED macro:CFrameWndExCMDIFrameWndExCPaneFrameWnd
De signatuur van de methode
OnMouseLeavegewijzigd om te voldoen aan de ON_WM_MOUSELEAVE macro:CMFCCaptionBarCMFCColorBarCMFCHeaderCtrlCMFCProperySheetListBoxCMFCRibbonBarCMFCRibbonPanelMenuBarCMFCRibbonRichEditCtrlCMFCSpinButtonCtrlCMFCToolBarVervangDezeTekstCMFCToolBarComboBoxEditCMFCToolBarEditCtrlCMFCAutoHideBar
De signatuur van
OnPowerBroadcastgewijzigd om overeen te komen met de ON_WM_POWERBROADCAST-macro.CFrameWndExCMDIFrameWndEx
De signatuur van
OnStyleChangedgewijzigd om overeen te komen met de ON_WM_STYLECHANGED macro:CMFCListCtrlCMFCStatusBar
Wijzig de naam van de interne methode
FontFamalyProcFontsinFontFamilyProcFonts.Talloze globale statische
CStringobjecten verwijderd om geheugenlekken in sommige situaties te voorkomen (vervangen door #defines) en de volgende klasselidvariabelen:CKeyBoardManager::m_strDelimiterCMFCPropertyGridProperty::m_strFormatCharCMFCPropertyGridProperty::m_strFormatShortCMFCPropertyGridProperty::m_strFormatLongCMFCPropertyGridProperty::m_strFormatUShortCMFCPropertyGridProperty::m_strFormatULongCMFCPropertyGridProperty::m_strFormatFloatCMFCPropertyGridProperty::m_strFormatDoubleCMFCToolBarImages::m_strPngResTypeCMFCPropertyGridProperty::m_strFormat
De signatuur van
CKeyboardManager::ShowAllAcceleratorsis gewijzigd en de parameter voor het scheidingsteken van de accelerator is verwijderd.Toegevoegd
CPropertyPage::GetParentSheet, en in deCPropertyPageklasse, roep het aan in plaats vanGetParentom het juiste bovenliggende bladvenster te verkrijgen, dat het ouder- of grootoudervenster vanCPropertyPagekan zijn. Mogelijk moet u uw code wijzigen om aan te roepenGetParentSheetin plaats vanGetParent.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:
GetDirectD2dFactoryGetWriteFactoryGetWICFactoryInitD2DReleaseD2DRefsIsD2DInitializedD2D1MakeRotateMatrixIn plaats van bijvoorbeeld
afxGlobalData.IsD2DInitializedte bellen, belAfxGetD2DState->IsD2DInitialized.
Verouderde ATL*.CPP-bestanden verwijderd uit de map \atlmfc\include\.
De initialisatie van
afxGlobalDatais verplaatst naar on-demand in plaats van tijdens de CRT-initialisatie om te voldoen aan deDLLMain-vereisten.De methode
RemoveButtonByIndextoegevoegd aan de klasseCMFCOutlookBarPane.CMFCCmdUsageCount::IsFreqeuntlyUsedCmdgecorrigeerd naarIsFrequentlyUsedCmd.Verschillende exemplaren van
RestoreOriginalstatenaarRestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).Ongebruikte methoden verwijderd uit
CDockablePane:SetCaptionStyle,IsDrawCaption,IsHideDisabledButtons, ,GetRecentSiblingPaneInfoenCanAdjustLayout.Verwijderd statische
CDockablePanelidvariabelenm_bCaptionTextenm_bHideDisabledButtons.Er is een onderdrukkingsmethode
DeleteStringtoegevoegd aanCMFCFontComboBox.Ongebruikte methoden verwijderd uit
CPane:GetMinLengthenIsLastPaneOnLastRow.De naam is gewijzigd
CPane::GetDockSiteRow(CDockingPanesRow *)inCPane::SetDockSiteRow.
Wijzigingen die fouten veroorzaken in Visual Studio 2010
Samensteller
Het
autotrefwoord 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_asserttrefwoord 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
/GScompileroptie 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
/GLcompileropties (Whole Program Optimization) als/clr(Common Language Runtime Compilation), wordt de/GLoptie 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:trigraphscompileroptie 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
/OPToptie (Optimalisaties) produceert een compilatietijdfout als u opgeeft/OPT:WIN98of/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()ofterminate()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 dechecked_*enunchecked_*functies verwijderd. En in de<iterator>> koptekst wordt dechecked_iteratorklasse verwijderd en is deunchecked_array_iteratorklasse toegevoegd.De
CComPtr::CComPtr(int)constructor wordt verwijderd. Met deze constructor kon eenCComPtrobject worden samengesteld uit de NULL macro, maar dit was onnodig en stond onzinnige constructies toe van niet-nul-gelijke gehele getallen.Een
CComPtrkan 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 daarvannullptr.De volgende
ctypelidfuncties zijn verwijderd:ctype::_Do_narrow_s,ctype::_Do_widen_s,ctype::_narrow_s, .ctype::_widen_sAls 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
CDocTemplateklasse. Deze nieuwe virtuele functie is CDocTemplate Class. De vorige versie vanOpenDocumentFilehad twee parameters. De nieuwe versie heeft drie parameters. Ter ondersteuning van de manager voor opnieuw opstarten moet elke klasse die is afgeleid vanCDocTemplate, de versie met drie parameters implementeren. De nieuwe parameter isbAddToMRU.
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
GetVersionofGetVersionExin 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_fltvoor 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_getis veranderd. Voorheen, wanneer een geldbedrag met meer breukcijfers dan werd gevraagd doorfrac_digitswerd geparsed, consumeerdedo_getze allemaal. Nu stoptdo_getu met parseren nadat u maximaalfrac_digitstekens 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_CRTATL-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
CTimeKlasse: DeCTimeklasse 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.
CFileDialogKlasse: Aangepaste sjablonen voor deCFileDialogklasse 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.CWndKlasse enCFrameWndklasse: deCWnd::GetMenuBarInfomethode is verwijderd.De
CFrameWnd::GetMenuBarInfomethode 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
stdoutenstderrniet 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
/MLcompilervlag 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).sprintfdrukt nu het negatieve teken van een getekende nul af.swprintfis gewijzigd om te voldoen aan de norm; hiervoor is nu een grootteparameter vereist. De vorm vanswprintfzonder een grootteparameter is afgeschaft._set_security_error_handleris verwijderd. Verwijder alle aanroepen naar die functie; de standaardhandler is een veel veiligere manier om beveiligingsfouten op te lossen.time_tis nu een 64-bits waarde (tenzij _USE_32BIT_TIME_T is gedefinieerd).De
_spawn- en_wspawn-functies latenerrnonu 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
/CLRof/CLR:PURE. De betrokken functies zijn_clear87, ,_clearfp,_control87,_controlfp,_fpreset, , ,_status87._statusfpU 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 destdnaamruimte. 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 devalarrayinhoud verloren en wordt deze vervangen door standaardwaarden. Deresize()methode is bedoeld om devalarraymethode 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_LEVELVisual 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
typedefniet toegestaan volgens de standaard en genereert nu een compilerfout (compilerfout C2513).boolis 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).