Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek popisuje všechny zásadní změny od sady Visual Studio 2015 zpět k sadě Visual Studio 2003. V tomto článku se výrazy "nové chování" nebo "teď" vztahují k sadě Visual Studio 2015 a novějším verzím. Termíny "staré chování" a "před" odkazují na Visual Studio 2013 a starší verze.
Informace o nejnovější verzi sady Visual Studio najdete v tématu Co je nového pro jazyk C++ v sadě Visual Studio a vylepšení shody jazyka C++ v sadě Visual Studio.
Poznámka:
Mezi sadou Visual Studio 2015 a Visual Studio 2017 neexistují žádné binární zásadní změny.
Když upgradujete na novou verzi sady Visual Studio, může dojít k chybám kompilace nebo modulu runtime v kódu, který se dříve zkompiloval a spustil správně. Změny v nové verzi, které způsobují takové problémy, se označují jako zásadní změny a obvykle je vyžadují úpravy ve standardu jazyka C++, podpisech funkcí nebo rozložení objektů v paměti.
Abyste se vyhnuli chybám za běhu, které jsou obtížné rozpoznat a diagnostikovat, doporučujeme nikdy staticky propojit binární soubory kompilované pomocí jiné verze kompilátoru. Když upgradujete projekt EXE nebo DLL, nezapomeňte také provést upgrade knihoven, na které odkazuje. Nepředávejte typy CRT (C Runtime) ani standardní knihovny C++ (standardní knihovna C++) mezi binárními soubory, včetně knihoven DLL, kompilovaných pomocí různých verzí kompilátoru. Další informace naleznete v tématu Potenciální chyby předávání objektů CRT přes hranice knihovny DLL.
Nepsat kód, který závisí na konkrétním rozložení objektu, který není rozhraním COM nebo objektem POD. Pokud takový kód napíšete, musíte zajistit, aby po upgradu fungoval. Další informace naleznete v tématu Přenositelnost na rozhraních ABI.
Kromě toho průběžná vylepšení shody kompilátoru můžou někdy změnit způsob, jakým kompilátor rozumí vašemu stávajícímu zdrojovému kódu. Během sestavení můžete například najít nové nebo jiné chyby nebo dokonce rozdíly v chování v kódu, který byl dříve sestaven a zdál se, že je správně spuštěný. I když tato vylepšení nejsou zásadními změnami, jako jsou ty, které jsou popsány v tomto dokumentu, možná budete muset udělat změny ve zdrojovém kódu, abyste mohli tyto problémy vyřešit:
Změny v souladu se sadou Visual Studio 2015
C Runtime Library (CRT)
Obecné změny
Refaktorované binární soubory
Knihovna CRT byla přepracována do dvou různých binárních souborů: Univerzální CRT (ucrtbase), která obsahuje většinu standardních funkcí, a knihovnu modulu runtime VC (vcruntime). Knihovna vcruntime obsahuje funkce související s kompilátorem, jako je zpracování výjimek a vnitřní funkce. Pokud používáte výchozí nastavení projektu, tato změna vás neovlivní, protože linker používá nové výchozí knihovny automaticky. Pokud jste nastavili vlastnost projektu Linker na Ignorovat všechny výchozí knihovny na Ano, nebo používáte možnost
/NODEFAULTLIBlinkeru na příkazovém řádku, musíte aktualizovat seznam knihoven (ve vlastnosti Dodatečné závislosti), aby zahrnoval nové, refaktorované knihovny. Nahraďte starou knihovnu CRT (libcmt.lib,libcmtd.lib,msvcrt.libmsvcrtd.lib) ekvivalentními refaktorovanými knihovnami. Pro každou ze dvou refaktorovaných knihoven existují statické (.lib) a dynamické (.dll) verze, a to produkční verze (bez přípony) a ladicí verze (s příponou "d"). Dynamické verze mají knihovnu importu, se kterou propojíte. Tyto dvě refaktorované knihovny jsou univerzální CRT, konkrétně ucrtbase.dll nebo ucrtbase.lib, ucrtbased.dll nebo ucrtbased.lib, a knihovna VC runtime,libvcruntime.libvcruntimeverze.dll alibvcruntimed.libvcruntimedverze.dll. Verze v sadě Visual Studio 2015 i Visual Studio 2017 je 140. Viz funkce knihovny CRT.
<locale.h>
localeconvFunkce
localeconvdeklarovaná v národním prostředí.h teď funguje správně, když je povolené národní prostředí pro jednotlivá vlákna. V předchozích verzích knihovny by tato funkce vracelalconvdata pro globální lokalizaci, nikoli pro lokalizaci vlákna.Pokud používáte národní prostředí pro jednotlivá vlákna, měli byste zkontrolovat použití
localeconv. Pokud váš kód předpokládá, želconvvrácená data jsou pro globální národní prostředí, měli byste je opravit.
<math.h>
Přetížení funkcí matematické knihovny jazyka C++
V předchozích verzích jsme
<math.h>definovali některé, ale ne všechny přetížení jazyka C++ pro funkce matematické knihovny. Zbytek přetížení byl v<cmath>hlavičkovém souboru. Kód, který obsahuje pouze<math.h>, může mít problémy s řešením přetížení funkce. Nyní jsou přetížení jazyka C++ odebrána z<math.h>a jsou nalezena pouze v<cmath>.Chcete-li vyřešit chyby, zahrňte
<cmath>pro získání deklarací funkcí, které byly odebrány z<math.h>. Tyto funkce byly přesunuty:-
double abs(double)afloat 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) -
floatalong doubleverze funkcí s plovoucí desetinou čárkou:acos,acosh,asin,asinh,atan,atanh,atan2,cbrt,ceil,copysign,cos,cosh,erf,erfc,exp,exp2,expm1,fabs,fdim,floor,fma,fmax,fmin,fmod,frexp,hypot,ilogb,ldexp,lgamma,llrint,llround,log,log10,log1p,log2,lrint,lround,modf,nearbyint,nextafter,nexttoward,remainder,remquo,rint,round,scalbln,scalbn,sin,sinh,sqrt,tan,tanh,tgammaatrunc
Pokud máte kód, který používá
abss typem s plovoucí desetinnou čárkou, který obsahuje pouze záhlaví<math.h>, verze s plovoucí desetinnou čárkou už nebudou k dispozici. Volání se teď vyřeší naabs(int), i když je použit argument typu plovoucí číslo, což způsobuje chybu:warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of dataOprava tohoto upozornění spočívá v nahrazení volání
absverzí s plovoucí desetinnou čárkouabs, napříkladfabspro argument typu double nebofabsfpro argument typu float, nebo zahrnutím hlavičky<cmath>a pokračováním v použitíabs.-
Shoda s pohyblivou řádovou čárkou
Byla provedena řada změn v matematické knihovně s cílem zlepšit soulad se specifikacemi IEEE-754 a C11, příloha F, s ohledem na zvláštní případy vstupů, jako jsou NaN a nekonečna. Například tiché vstupy NaN, které byly často považovány za chyby v předchozích verzích knihovny, již nejsou považovány za chyby. Viz standard IEEE 754 a příloha F standardu C11.
Tyto změny nezpůsobí chyby v době kompilace, ale můžou způsobit, že se programy budou chovat jinak a správněji podle standardu.
FLT_ROUNDS
V sadě Visual Studio 2013 se makro FLT_ROUNDS rozšířilo na konstantní výraz, což bylo nesprávné, protože režim zaokrouhlování je možné konfigurovat za běhu, například voláním fesetroundu. Makro FLT_ROUNDS je teď dynamické a správně odráží aktuální režim zaokrouhlování.
<new> a <new.h>
newadeleteV předchozích verzích knihovny byly nové a odstraněné funkce operátoru definované implementací exportovány z knihovny DLL modulu runtime (například msvcr120.dll). Tyto funkce operátoru jsou nyní vždy staticky propojeny s binárními soubory, i když používáte knihovny DLL modulu runtime.
Nejedná se o zásadní změnu nativního nebo smíšeného kódu (
/clr), ale pro kód zkompilovaný jako /clr:pure, tato změna může způsobit, že se váš kód nepodaří zkompilovat. Pokud kód zkompilujete jako/clr:pure, možná budete muset kvůli této změně přidat#include <new>nebo#include <new.h>obejít chyby sestavení. Tato/clr:puremožnost je v sadě Visual Studio 2015 zastaralá a v sadě Visual Studio 2017 není podporovaná. Kód, který musí být čistý, by měl být portován do C#.
<process.h>
_beginthreada_beginthreadexFunkce
_beginthreada_beginthreadexnyní obsahují odkaz na modul, ve kterém je procedura vlákna definována po dobu trvání vlákna. To pomáhá zajistit, že se moduly nevykládají, dokud vlákno neběží až do dokončení.
<stdarg.h>
va_starta odkazové typyPři kompilaci kódu jazyka C++ se nyní v době kompilace ověřuje, že předaný argument
va_startnení typu reference. Argumenty typu odkazu jsou zakázány standardním jazykem C++.
<stdio.h> a <conio.h>
Řada funkcí printf a scanf je teď definovaná interně.
Definice všech funkcí
printfascanfbyly přesunuty inline do<stdio.h>,<conio.h>a dalších CRT hlaviček. Tato zásadní změna vede k chybě linkeru (LNK2019, nevyřešený externí symbol) ve všech programech, které deklarovaly tyto funkce lokálně bez zahrnutí odpovídajících hlaviček CRT. Pokud je to možné, měli byste kód aktualizovat tak, aby zahrnoval hlavičky CRT (to znamená přidat#include <stdio.h>) a vložené funkce, ale pokud nechcete kód upravit tak, aby zahrnoval tyto soubory hlaviček, je alternativním řešením přidatlegacy_stdio_definitions.libdo vstupu linkeru.Pokud chcete tuto knihovnu přidat do vstupu linkeru v integrovaném vývojovém prostředí, otevřete místní nabídku uzlu projektu, zvolte Vlastnosti, poté v dialogovém okně Vlastnosti projektu zvolte Linker a upravte Vstup linkeru tak, aby zahrnoval
legacy_stdio_definitions.libdo seznamu odděleného středníkem.Pokud váš projekt odkazuje na statické knihovny, které byly zkompilovány s verzí sady Visual Studio starší než 2015, může linker hlásit nevyřešený externí symbol. Tyto chyby mohou odkazovat na vnitřní definice pro
_iob,_iob_funcnebo související importy pro určité<stdio.h>funkce ve formě imp*. Společnost Microsoft doporučuje při upgradu projektu překompilovat všechny statické knihovny s nejnovější verzí kompilátoru a knihoven jazyka C++. Pokud je knihovna třetí stranou, pro kterou zdroj není k dispozici, měli byste buď požádat o aktualizovaný binární soubor od třetí strany, nebo zapouzdřit použití této knihovny do samostatné knihovny DLL, kterou kompilujete se starší verzí kompilátoru a knihoven.Upozornění
Pokud propojujete s Windows SDK 8.1 nebo starší verzí, můžete narazit na tyto nevyřešené chyby externího symbolu. V takovém případě byste měli chybu vyřešit přidáním legacy_stdio_definitions.lib do vstupu linkeru, jak je popsáno výše.
Při řešení potíží s nevyřešenými chybami symbolů můžete pomocí
dumpbin.exeprozkoumat symboly definované v binárním souboru. Zkuste následující příkazový řádek zobrazit symboly definované v knihovně.dumpbin.exe /LINKERMEMBER somelibrary.libzíská a _getws
Funkce gets a _getws byly odebrány. Funkce Gets byla odebrána ze standardní knihovny jazyka C v C11, protože ji nelze bezpečně použít. Funkce _getws byla rozšířením Microsoftu, které bylo ekvivalentní funkci gets, ale pro široké řetězce. Jako alternativy k těmto funkcím zvažte použití fgetů, fgetws, gets_s a _getws_s.
_cgets a _cgetws
Funkce _cgets a _cgetws byly odebrány. Jako alternativy k těmto funkcím zvažte použití _cgets_s a _cgetws_s.
Formátování nekonečna a NaN
V předchozích verzích by se nekonečna a NaN naformátovaly pomocí specifických řetězců sentinelů pro MSVC.
Nekonečno: 1,#INF
Quiet NaN (tichý NaN): 1.#QNAN
Signální NaN: 1.#SNAN
Nedefinované NaN: 1.#IND
Některé z těchto formátů můžou mít před znaménko a můžou být formátované mírně odlišně v závislosti na šířce a přesnosti pole (někdy s neobvyklými efekty by například
printf("%.2f\n", INFINITY)tiskl 1,#J, protože #INF by bylo "zaokrouhleno" na dvoucifernou přesnost). C99 zavedl nové požadavky na to, jak se mají formátovat nekonečna a NaN. Implementace MSVC teď vyhovuje těmto požadavkům. Nové řetězce jsou následující:Nekonečno: inf
Quiet NaN: nan
Signalizující NaN: nan(snan)
Neurčené NaN: nan(ind)
Kterákoli z těchto možností může mít předponu ve formě znaménka. Pokud se použije specifikátor formátu s velkými písmeny (%F místo %f), vytisknou se řetězce velkými písmeny (
INFmístoinf), jak je třeba.Funkce scanf byly upraveny tak, aby parsovaly tyto nové řetězce, takže tyto řetězce nyní procházejí přes
printfascanf.Formátování a parsování čísel s plovoucí desetinnou čárkou
Byly zavedeny nové algoritmy analýzy a formátování s plovoucí desetinnou čárkou, aby se zlepšila správnost. Tato změna ovlivňuje řadu funkcí printf a scanf a funkcí, jako je strtod.
Staré algoritmy formátování by vygenerovaly pouze omezený počet číslic a pak by vyplnily zbývající desetinná místa nulou. Obvykle mohly generovat řetězce, které by se vrátily zpět na původní hodnotu s plovoucí čárkou, ale nebyly ideální, pokud jste potřebovali přesnou hodnotu (nebo její nejbližší desítkové vyjádření). Nové algoritmy formátování generují tolik číslic, kolik je potřeba k reprezentaci hodnoty (nebo k vyplnění zadané přesnosti). Jako příklad zlepšení, zvažte výsledky při tisku velké mocniny dvou:
printf("%.0f\n", pow(2.0, 80))Starý výstup:
1208925819614629200000000Nový výstup:
1208925819614629174706176Staré algoritmy analýzy by považovaly pouze 17 významných číslic ze vstupního řetězce a zbývající číslice by zahodily. Tento přístup stačí k vygenerování úzké aproximace hodnoty představované řetězcem a výsledek je obvykle velmi blízko správnému zaokrouhlení výsledku. Nová implementace považuje všechny současné číslice a vytvoří správně zaokrouhlený výsledek pro všechny vstupy (až 768 číslic). Kromě toho tyto funkce nyní respektují režim zaokrouhlování (lze ovládat pomocí fesetroundu). Toto je potenciálně změna chování, která může narušit funkčnost, protože tyto funkce mohou produkovat různé výsledky. Nové výsledky jsou vždy správnější než staré výsledky.
Hexadecimální parsování a parsování plovoucí čárky pro nekonečno/NaN
Algoritmy parsování s plovoucí desetinnou čárkou nyní budou parsovat šestnáctkové řetězce s plovoucí desetinnou čárkou (například řetězce generované specifikátory formátu printf %a a %A) a všechny řetězce nekonečna a řetězce NaN generované funkcemi
printf, jak je popsáno výše.%A a %a nulové doplnění
Specifikátory formátu %a a %A formátují číslo s plovoucí řádovou čárkou jako šestnáctkovou mantisu a binární exponent. V předchozích verzích by funkce
printfnesprávně doplnily řetězce nulami. Napříkladprintf("%07.0a\n", 1.0)by vytiskl 00x1p+0, místo 0x01p+0. Tato chyba byla opravena.Přesnost %A a %a
Výchozí přesnost specifikátorů formátu %A a %a je 6 v předchozích verzích knihovny. Výchozí přesnost je nyní 13 pro shodu se standardem C.
Jedná se o změnu chování za běhu ve výstupu jakékoli funkce, která používá formátovací řetězec s %A nebo %a. Ve starém chování může být výstup používající specifikátor %A "1.1A2B3Cp+111". Výstup pro stejnou hodnotu je "1.1A2B3C4D5E6F7p+111". Pokud chcete získat staré chování, můžete zadat přesnost, například %.6A. Viz specifikace přesnosti.
Specifikátor %F
Specifikátor formátu nebo převodu %F je teď podporovaný. Funkčně odpovídá formátovacímu specifikátoru %f, s výjimkou toho, že nekonečna a NaN jsou formátována velkými písmeny.
V předchozích verzích se implementace použila k analýze F a N jako modifikátorů délky. Toto chování se datovalo zpět do doby segmentovaných adresních prostorů: tyto modifikátory délky byly použity k označení dalekých a blízkých ukazatelů, v uvedeném pořadí, jako v %Fp nebo %Ns. Toto chování bylo odebráno. Pokud je %F zjištěn, je nyní považován za specifikátor formátu %F; Pokud je zjištěna hodnota %N, považuje se nyní za neplatný parametr.
Formátování exponentu
Specifikátory formátu %e a %E naformátují číslo s plovoucí desetinnou čárkou jako desetinnou mantisu a exponent. Specifikátory formátu %g a %G také v některých případech formátují čísla v tomto formuláři. V předchozích verzích by CRT vždy vygeneroval řetězce s trojcifernými exponenty. Například
printf("%e\n", 1.0)by se vytisklo číslo 1,000000e+000, což bylo nesprávné. Jazyk C vyžaduje, aby byl exponent reprezentován pouze jednou nebo dvěma číslicemi, budou vytištěny pouze dvě číslice.V aplikaci Visual Studio 2005 byl zaveden globální přepínač shody: _set_output_format. Program může tuto funkci volat s argumentem _TWO_DIGIT_EXPONENT, aby bylo možné povolit odpovídající exponentní tisk. Výchozí chování bylo změněno na režim tisku exponentů, který odpovídá standardům.
Ověření řetězce formátu
V předchozích verzích by funkce
printfascanftiše přijímaly mnoho neplatných formátových řetězců, někdy s neobvyklými efekty. Například %hlhlhld by byl považován za %d. Všechny neplatné řetězce formátu jsou nyní považovány za neplatné parametry.Ověření řetězce v režimu fopen
Ve starších verzích funkce z rodiny
fopentiše přijímaly některé neplatné řetězce režimu, jako napříkladr+b+. Neplatné řetězce režimu jsou nyní zjišťovány a považovány za neplatné parametry.režim _O_U8TEXT
Funkce _setmode nyní správně hlásí režim pro datové proudy otevřené v režimu in_O_U8TEXT. V předchozích verzích knihovny by takové proudy hlásila jako otevřené v režimu _O_WTEXT.
Jedná se o zásadní změnu, pokud váš kód interpretuje režim _O_WTEXT pro datové proudy, kde kódování je UTF-8. Pokud vaše aplikace nepodporuje UTF_8, zvažte přidání podpory pro toto stále častější kódování.
snprintf a vsnprintf
Funkce snprintf a vsnprintf jsou teď implementované. Starší kód často poskytoval definice verzí maker těchto funkcí, protože nebyly implementovány knihovnou CRT, ale už nejsou potřeba v novějších verzích. Pokud je snprintf nebo vsnprintf definován jako makro před zahrnutím
<stdio.h>, kompilace nyní selže s chybou, která označuje, kde bylo makro definováno.Oprava tohoto problému obvykle spočívá v odstranění všech deklarací
snprintfnebovsnprintfv uživatelském kódu.Tmpnam generuje použitelné názvy souborů.
V předchozích verzích funkce
tmpnamatmpnam_svygenerovaly názvy souborů v kořenovém adresáři jednotky (například \sd3c.). Tyto funkce teď generují použitelné cesty k názvům souborů v dočasném adresáři.Zapouzdření SOUBORU
V předchozích verzích byl kompletní typ FILE veřejně definován v
<stdio.h>, což umožňovalo uživatelskému kódu přístup k jeho vnitřní struktuře a její úpravu. Knihovna byla změněna tak, aby skrývala podrobnosti implementace. V rámci této změny je teď SOUBOR definovaný<stdio.h>neprůmyslným typem a jeho členové jsou nepřístupní mimo samotný CRT._outp a _inp
Funkce _outp, _outpw, _outpd, _inp, _inpw a _inpd byly odebrány.
<stdlib.h>, <malloc.h> a <sys/stat.h>
strtof a wcstof
Funkce
strtofawcstofnepodařilo se nastaviterrnona ERANGE, když hodnota nebyla reprezentovatelná jako float. Tato chyba byla specifická pro tyto dvě funkce; ,strtodwcstodstrtoldawcstoldfunkce nebyly ovlivněny. Tento problém byl opraven a jedná se o změnu narušující běh programu.Zarovnané funkce přidělení
V předchozích verzích by zarovnané funkce přidělování (
_aligned_malloc_aligned_offset_mallocatd.) bezobslužně přijímaly požadavky na blok se zarovnáním 0. Požadované zarovnání musí být mocnina dvou, což neplatí pro nulu. Požadované zarovnání 0 je nyní považováno za neplatný parametr. Tento problém je opravený a jedná se o změnu způsobující chybu za běhu.Funkce haldy
Funkce
_heapadda funkce_heapset_heapusedbyly odebrány. Tyto funkce jsou nefunkční od doby, co byla CRT aktualizována, která začala používat haldu Windows.smallheap
Možnost
smallheappropojení byla odebrána. Viz Možnosti propojení._stat
Rodina funkcí
_statvyužíváCreateFilev sadě Visual Studio 2015, místoFindFirstFilejako v sadě Visual Studio 2013 a dřívějších verzích. To znamená, že_statna cestě končící lomítkem proběhne úspěšně, pokud cesta odkazuje na adresář, na rozdíl od dříve, kdy by funkce chybovala s nastaveným parametremerrnoENOENT.
<string.h>
wcstokPodpis
wcstokfunkce byl změněn tak, aby odpovídal tomu, co vyžaduje standard C. Ve starších verzích knihovny byla definice této funkce:wchar_t* wcstok(wchar_t*, wchar_t const*)Použil interní kontext pro jednotlivá vlákna ke sledování stavu napříč voláními, jak je tomu u
strtok. Funkce teď má podpiswchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**)a vyžaduje, aby volající předal kontext jako třetí argument funkci.Byla přidána nová
_wcstokfunkce se starým podpisem pro usnadnění přenosu. Při kompilaci kódu jazyka C++ existuje také vložené přetíženíwcstok, které má starý podpis. Toto přetížení je označeno jako zastaralé. Ve zdrojovém kódu jazyka C můžete definovat `define_CRT_NON_CONFORMING_WCSTOK`, aby se použilo_wcstokmístowcstok.
<time.h>
hodiny
V předchozích verzích byla funkce
clockimplementována pomocí rozhraní APIGetSystemTimeAsFileTimesystému Windows. Při této implementaci byla hodinová funkce citlivá na systémový čas, a proto nebyla nutně monotónní. Funkce hodin byla reimplementována z hlediskaQueryPerformanceCountera je nyní monotónní.fstat a _utime
V předchozích verzích
_stat,fstata_utimefunkce zpracovávaly letní čas nesprávně. Před verzí Visual Studio 2013 všechny tyto funkce nesprávně upravily standardní čas, jako by šlo o letní čas.V sadě Visual Studio 2013 se problém vyřešil ve
_statskupině funkcí, ale podobné problémy vfstatřadách funkcí a_utimerodiny funkcí nebyly opraveny. Tato částečná oprava vedla k problémům kvůli nekonzistence mezi funkcemi.fstata_utimeřady funkcí byly nyní opraveny, všechny tyto funkce nyní zpracovávají letní čas správně a konzistentně.asctime
V předchozích verzích funkce
asctimedoplnila jednociferné dny úvodní nulou, například:Fri Jun 06 08:00:00 2014. Specifikace vyžaduje, aby tyto dny byly zarovnány úvodní mezerou, jako vFri Jun 6 08:00:00 2014. Tento problém byl opraven.strftime a wcsftime
strftimeFunkcewcsftimeteď podporují specifikátory formátu %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %u a %V. Modifikátory E a O se navíc analyzují, ale ignorují.Specifikátor formátu %c je určen jako vytvoření "odpovídající reprezentace data a času" pro aktuální národní prostředí. V národním prostředí jazyka C musí být tato reprezentace stejná jako
%a %b %e %T %Y, stejná forma, jakou vytváříasctime. V předchozích verzích specifikátor formátu %c nesprávně formátoval časy pomocíMM/DD/YY HH:MM:SSreprezentace. Tento problém byl opraven.timespec a TIME_UTC
Hlavička
<time.h>teď definujetimespectyp a funkci ze standardutimespec_getC11. Kromě toho je nyní definováno makro TIME_UTC pro použití stimespec_getfunkcí. Tato aktualizace představuje zásadní změnu kódu, která má konfliktní definici pro kterýkoli z těchto identifikátorů.CLOCKS_PER_SEC
Makro CLOCKS_PER_SEC se teď rozbalí na celé číslo typu
clock_t, jak to vyžaduje jazyk C.
Standardní knihovna C++
Aby bylo možné povolit nové optimalizace a kontroly ladění, implementace C++ Standardní knihovny ve Visual Studiu záměrně narušuje binární kompatibilitu z jedné verze na další. Proto při použití standardní knihovny C++ nelze objektové soubory a statické knihovny, které jsou kompilovány pomocí různých verzí, směšovat v jednom binárním souboru (EXE nebo DLL) a objekty standardní knihovny C++ nelze předávat mezi binárními soubory, které jsou kompilovány pomocí různých verzí. Míchání objektů tohoto typu vyvolává chyby linkeru týkající se neshod _MSC_VER. (_MSC_VER je makro, které obsahuje hlavní verzi kompilátoru – například 1800 pro Visual Studio 2013.) Tato kontrola nedokáže rozpoznat kombinování knihoven DLL a nedokáže rozpoznat kombinování, které zahrnuje Visual Studio 2008 nebo starší.
Standardní knihovna C++ – zahrnutí souborů
V hlavičkách standardní knihovny C++ byly provedeny některé změny ve struktuře zahrnutí. Hlavičky standardní knihovny jazyka C++ mohou zahrnovat jedna druhou nezpůsobem, který není specifikován. Obecně byste měli napsat kód tak, aby pečlivě zahrnoval všechny hlavičky, které potřebuje podle standardu C++, a nespoléhá na to, které hlavičky standardní knihovny C++ zahrnují další hlavičky standardní knihovny C++. Díky tomu je kód přenosný napříč verzemi a platformami. Nejméně dvě změny hlaviček v sadě Visual Studio 2015 ovlivňují uživatelský kód. Za prvé,
<string>již neobsahuje<iterator>. Za druhé,<tuple>nyní deklarujestd::arraybez zahrnutí všech<array>, což může přerušit kód pomocí následující kombinace konstrukcí kódu: váš kód má proměnnou s názvem "array" a máte direktivu použití "using namespace std;" a zahrnete hlavičku standardní knihovny jazyka C++ (například<functional>) zahrnující<tuple>, která nyní deklarujestd::array.steady_clock
Implementace
<chrono>steady_clockse změnila tak, aby splňovala standardní požadavky jazyka C++ na stálost a monotonitu.steady_clockje nyní založen naQueryPerformanceCounterahigh_resolution_clockje nyní typedef prosteady_clock. V důsledku toho je ve Visual Studiosteady_clock::time_pointnyní typedef nachrono::time_point<steady_clock>; to však nemusí nutně platit pro jiné implementace.alokátory a konstanta 'const'
Nyní vyžadujeme, aby porovnávání rovnosti a nerovnosti alokátorů přijímalo const argumenty na obou stranách. Pokud vaše alokátory definují tyto operátory takto,
bool operator==(const MyAlloc& other)pak byste je měli aktualizovat a deklarovat jako členy const:
bool operator==(const MyAlloc& other) constconst – prvky
Standard C++ má vždy zakázané kontejnery prvků const (například
vector<const T>).set<const T>Visual Studio 2013 a starší tyto kontejnery přijali. V aktuální verzi se takové kontejnery nepodaří zkompilovat.std::allocator::deallocate
V aplikaci Visual Studio 2013 a dřívějších verzích
std::allocator::deallocate(p, n)ignoroval argument předaný pro n. Standard jazyka C++ vždy vyžaduje, aby n musel být roven hodnotě předané jako první argument vyvoláníallocate, které vrátilo p. V aktuální verzi se ale zkontroluje hodnota n . Kód, který předává argumenty pro n , které se liší od standardních požadavků, může při běhu dojít k chybovému ukončení.hash_map a hash_set
Nestandardní hlavičkové soubory
<hash_map>a<hash_set>jsou ve Visual Studio 2015 zastaralé a budou odstraněny v budoucí verzi. Použijte<unordered_map>a<unordered_set>místo toho.komparátory a operátory()
Asociativní kontejnery (rodina
<map>) nyní vyžadují, aby jejich komparátory měly operátory volání funkce s konst-volatelnými operátory. Následující kód v deklaraci srovnávací třídy se teď nepodaří zkompilovat:bool operator()(const X& a, const X& b)Pokud chcete tuto chybu vyřešit, změňte deklaraci funkce na:
bool operator()(const X& a, const X& b) consttypové vlastnosti
Staré názvy pro vlastnosti typu ze starší verze konceptu C++ byly odebrány. Byly změněny v C++11 a aktualizovány na hodnoty C++11 v sadě Visual Studio 2015. V následující tabulce jsou uvedeny staré a nové názvy.
Starý název Nový název přidat_odkaz přidat_lvalue_reference má_výchozí_konstruktor (has_default_constructor) je možné vytvořit pomocí výchozího konstruktoru má konstruktor kopie (has_copy_constructor) je_kopírovatelná_sestrojitelnost has_move_constructor is_move_constructible has_nothrow_constructor (má konstruktér bez výjimek) is_nothrow_default_constructible has_nothrow_default_constructor (má výchozí konstruktor, který nevyhazuje výjimky) is_nothrow_default_constructible has_nothrow_copy (zajišťuje kopírování bez vyvolání výjimek) is_nothrow_copy_constructible In cases where translation is deemed necessary or beneficial: - má_copy_konstruktor_bez_výjimky is_nothrow_copy_constructible má_konstruktor_bezpříhozového_přesunu is_nothrow_move_constructible má_bezvýjimkový_přiřazení is_nothrow_copy_assignable has_nothrow_copy_assign is_nothrow_copy_assignable má_bezvýjimkové_přiřazení_přesunu is_nothrow_move_assignable má_triviální_konstruktor is_trivially_default_constructible (je triviálně výchozí libovolně vytvořitelný) má triviální výchozí konstruktor is_trivially_default_constructible (je triviálně výchozí libovolně vytvořitelný) má_triviální_kopii is_trivially_copy_constructible If localization is not required and it's a recognized term, it should remain unchanged. If translation is needed, consult a technical dictionary or subject matter expert. is_trivially_přesouvatelný_konstruktibilní má_triviální_přiřazení je_triviálně_přiřaditelné_kopírováním má_triviální_přiřazení_úkolu_přesunu is_trivially_move_assignable má triviální destruktor je_triviálně_ničitelné launch::any a launch::sync politiky
Nestandardní zásady
launch::anyalaunch::syncbyly odebrány. Místo toho prolaunch::anypoužijtelaunch:async | launch:deferred. Prolaunch::syncpoužijtelaunch::deferred. Viz launch Enumeration.
MFC a ATL
Knihovna MFC (Microsoft Foundation Classes)
není už součástí typické instalace sady Visual Studio kvůli své velké velikosti. Pokud chcete nainstalovat prostředí MFC, zvolte možnost Vlastní instalace v instalačním programu sady Visual Studio 2015. Pokud už máte nainstalovanou sadu Visual Studio 2015, můžete prostředí MFC nainstalovat opětovným spuštěním instalace sady Visual Studio . Zvolte možnost Vlastní instalace a pak zvolte Třídy služby Microsoft Foundation. Instalační program sady Visual Studio můžete spustit z Ovládacích panelů v části Programy a funkce nebo z instalačního média.
Distribuovatelný balíček Visual C++ stále zahrnuje i tuto knihovnu.
Concurrency Runtime
Výnos makra z Windows.h v konfliktu s souběžností::Context::Yield
Modul Concurrency Runtime dříve použil
#undefk nedefinaci makra Yield, aby nedocházelo ke konfliktům mezi makrem Yield definovaným ve Windows.h aconcurrency::Context::Yieldfunkcí. Tento#undefbyl odstraněn a bylo přidáno nové nekonfliktní ekvivalentní volání API concurrency::Context::YieldExecution. Pokud chcete obejít konflikty s Yield, můžete aktualizovat kód tak, aby místo toho volal funkciYieldExecution, nebo ohraničit název funkceYielddo závorek v místech volání, jak je znázorněno v následujícím příkladu:(concurrency::Context::Yield)();
Vylepšení shody kompilátoru v sadě Visual Studio 2015
Při upgradu kódu z předchozích verzí můžete také narazit na chyby kompilátoru, které jsou způsobeny vylepšeními shody v sadě Visual Studio 2015. Tato vylepšení neporušují binární kompatibilitu ze starších verzí sady Visual Studio, ale můžou způsobit chyby kompilátoru, ve kterých se předtím nevygenerovaly žádné. Další informace najdete v tématu Visual C++ What's New 2003 až 2015.
V sadě Visual Studio 2015 můžou probíhající vylepšení souladu kompilátoru někdy změnit způsob, jakým kompilátor rozumí vašemu existujícímu zdrojovému kódu. V důsledku toho můžete během sestavení narazit na nové nebo odlišné chyby nebo dokonce na odlišnosti v chování kódu, který se dříve sestavil a zdál se správně spuštěný.
Tyto rozdíly naštěstí mají malý nebo žádný vliv na většinu zdrojového kódu. Pokud jsou k vyřešení těchto rozdílů potřeba zdrojový kód nebo jiné změny, opravy jsou obvykle malé a jednoduché. Zahrnuli jsme mnoho příkladů dříve přijatelného zdrojového kódu, které možná bude potřeba změnit (před) a jejich opravy (po).
I když tyto rozdíly můžou ovlivnit zdrojový kód nebo jiné artefakty sestavení, nemají vliv na binární kompatibilitu mezi aktualizacemi verzí sady Visual Studio. Zásadní změna je vážnější a může ovlivnit binární kompatibilitu, ale tyto druhy přerušení binární kompatibility se vyskytují pouze mezi hlavními verzemi sady Visual Studio, například mezi sadou Visual Studio 2013 a sadou Visual Studio 2015. Informace o zásadních změnách, ke kterým došlo mezi sadou Visual Studio 2013 a Visual Studio 2015, najdete v tématu Změny shody sady Visual Studio 2015.
Vylepšení kompatibility v sadě Visual Studio 2015
/Zc:forScope- přepínač
Možnost
/Zc:forScope-kompilátoru je zastaralá a bude odebrána v budoucí verzi.Command line warning D9035: option 'Zc:forScope-' has been deprecated and will be removed in a future releaseTato možnost se obvykle použila k povolení nestandardního kódu, který používá proměnné smyčky za bodem, kde by podle standardu měly být mimo rozsah. Bylo nutné pouze v případě, že jste kompilovali s
/Zamožností, protože bez/Zapoužití proměnné smyčky for po ukončení smyčky je vždy povoleno. Pokud vás nezajímá shoda se standardy (například pokud váš kód nemá být přenositelný do jiných kompilátorů), můžete tuto možnost vypnout/Za(nebo nastavit vlastnost Disable Language Extensions na Ne). Pokud vás zajímá psaní přenosného kódu vyhovujícího standardům, měli byste kód přepsat tak, aby odpovídal standardu přesunutím deklarace těchto proměnných do bodu mimo smyčku.// 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 }/ZgMožnost kompilátoruMožnost kompilátoru
/Zg(Generování prototypů funkcí) už není dostupná. Tato možnost kompilátoru byla dříve zastaralá.Testy jednotek s C++/CLI už nemůžete spouštět z příkazového řádku s mstest.exe. Místo toho použijte vstest.console.exe. Viz VSTest.Console.exe možnosti příkazového řádku.
proměnlivé klíčové slovo
mutableSpecifikátor třídy úložiště už není povolený na místech, kde se dříve zkompiloval bez chyby. Kompilátor teď zobrazí chybu C2071 (neplatná třída úložiště). Podle standardumutablelze specifikátor použít pouze na názvy datových členů třídy a nelze jej použít u názvů deklarovaných const nebo static a nelze jej použít pro referenční členy.Představte si například následující kód:
struct S { mutable int &r; };Předchozí verze kompilátoru to přijali, ale teď kompilátor zobrazí následující chybu:
error C2071: 'S::r': illegal storage classPokud chcete chybu opravit, odeberte redundantní
mutableklíčové slovo.char_16_t a char32_t
Už nemůžete používat
char16_tanichar32_tjako aliasy vtypedef, protože tyto typy jsou nyní považovány za předdefinované. Pro uživatele a autory knihoven bylo běžné definovatchar16_tachar32_tjako aliasyuint16_tauint32_tv uvedeném pořadí.#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; }Chcete-li aktualizovat kód, odeberte
typedefdeklarace a přejmenujte všechny ostatní identifikátory, které s těmito názvy kolidují.Parametry šablony bez typu
Při zadávání explicitních argumentů šablony se teď správně kontroluje kompatibilita typů s určitým kódem, který zahrnuje parametry šablony jiného typu. Například následující kód se zkompiloval bez chyby v předchozích verzích sady 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>(); }Aktuální kompilátor správně zobrazí chybu, protože typ parametru šablony neodpovídá argumentu šablony (parametr je ukazatel na člen const, ale funkce f není 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'Pokud chcete tuto chybu vyřešit v kódu, ujistěte se, že typ argumentu šablony, který používáte, odpovídá deklarovanému typu parametru šablony.
__declspec(align)Kompilátor už nepřijímá
__declspec(align)na funkcích. Tento konstruktor byl vždy ignorován, ale nyní vytvoří chybu kompilátoru.error C3323: 'alignas' and '__declspec(align)' are not allowed on function declarationsChcete-li tento problém vyřešit, odeberte
__declspec(align)z deklarace funkce. Vzhledem k tomu, že neměl žádný vliv, odebrání nic nemění.Ošetření výjimek
Zpracování výjimek má několik změn. Za prvé, objekty výjimek musí být buď kopírovatelné nebo pohyblivé. Následující kód zkompilovaný v sadě Visual Studio 2013, ale nekompiluje se v sadě Visual Studio 2015:
struct S { public: S(); private: S(const S &); }; int main() { throw S(); // error }Problémem je, že konstruktor kopírování je soukromý, takže objekt nelze zkopírovat tak, jak se děje v normálním průběhu zpracování výjimky. Totéž platí při deklaraci
explicitkonstruktoru kopírování .struct S { S(); explicit S(const S &); }; int main() { throw S(); // error }Chcete-li aktualizovat kód, ujistěte se, že kopírovací konstruktor vašeho objektu výjimky je
publica není označenexplicit.Zachycení výjimky podle hodnoty také vyžaduje, aby objekt výjimky byl kopírovatelný. Následující kód zkompilovaný v sadě Visual Studio 2013, ale nekompiluje se v sadě Visual Studio 2015:
struct B { public: B(); private: B(const B &); }; struct D : public B {}; int main() { try { } catch (D d) // error { } }Tento problém můžete vyřešit změnou typu parametru
catchna odkaz.catch (D& d) { }Řetězcové literály následované makry
Kompilátor teď podporuje uživatelsky definované literály. V důsledku toho se řetězcové literály následované makry bez jakýchkoli mezer interpretují jako literály definované uživatelem, což může vést k chybám nebo k neočekávaným výsledkům. Například v předchozích kompilátorech se následující kód úspěšně zkompiloval:
#define _x "there" char* func() { return "hello"_x; } int main() { char * p = func(); return 0; }Kompilátor interpretoval tento kód jako řetězcový literál "hello", za kterým následuje makro, které je rozvinuto na "there", a potom byly tyto dva řetězcové literály spojeny do jednoho. V sadě Visual Studio 2015 kompilátor interpretuje tuto sekvenci jako literál definovaný uživatelem, ale protože neexistuje žádná odpovídající uživatelsky definovaná literála
_x, zobrazí chybu.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?Chcete-li tento problém vyřešit, přidejte mezeru mezi řetězcový literál a makro.
Sousední řetězcové literály
Podobně jako v předchozím případě se vzhledem ke změnám souvisejícím s parsováním řetězců vykládaly sousední řetězcové literály (ať už široké nebo úzké znakové literály) bez prázdných znaků jako jediný zřetězený řetězec v předchozích verzích Visual C++. V aplikaci Visual Studio 2015 teď musíte mezi dva řetězce přidat mezeru. Například musí být změněn následující kód:
char * str = "abc""def";Pokud chcete tento problém vyřešit, přidejte mezi tyto dva řetězce mezeru:
char * str = "abc" "def";Nové umístění a odstranění
Došlo ke změně operátoru
deletes cílem uvést ho do souladu se standardem C++14. Podrobnosti o změně standardů najdete na stránce C++ Sized Deallocation. Změny přidávají formu globálníhodeleteoperátoru, který přebírá parametr velikosti. Změna způsobující chybu spočívá v tom, že pokud jste dříve používali operátordeletese stejným podpisem (aby odpovídal operátoru umístění new), zobrazí se chyba kompilátoru (C2956, ke které dochází v okamžiku, kdy se použije operátor umístění new, protože jde o pozici v kódu, kde se kompilátor pokusí identifikovat odpovídajícídeleteoperátor).Funkce
void operator delete(void *, size_t)byla operátorem odstranění umístění, který odpovídá nové funkcivoid * operator new(size_t, size_t)umístění v jazyce C++11. S dealokací velikosti v C++14 je nyní tato funkce delete obvyklou funkcí dealokace (globální operátor). Standard vyžaduje, aby pokud použití nové umístění vyhledá odpovídající funkci odstranění a najde obvyklou funkci přidělení, program je špatně vytvořen.Předpokládejme například, že váš kód definuje jak placement new, tak placement delete:
void * operator new(std::size_t, std::size_t); void operator delete(void*, std::size_t) noexcept;K problému dochází z důvodu shody v podpisech funkce mezi vámi definovaným operátorem placement delete a novým globálním operátorem
delete. Zvažte, zda můžete pro jakýkoli operátor placement new adeletepoužít jiný typ nežsize_t. Typsize_ttypedefzávisí na kompilátoru; prounsigned intv MSVC je totypedef. Dobrým řešením je použít výčtový typ, například tento:enum class my_type : size_t {};Pak změňte definici placement new a
deletea jej použijte jako druhý argument místosize_t. Budete také muset aktualizovat volání operatoru placement new, aby se předal nový typ (například pomocístatic_cast<my_type>přetypování z celočíselné hodnoty) a přetypovat definicinewadeletezpět na typ integer. Pro tento typ není nutné použítenum. Typ třídy ssize_tčlenem by také fungoval.Alternativním řešením je, že můžete zcela eliminovat placement new. Pokud váš kód používá placement new pro implementaci fondu paměti, kde je argumentem umístění velikost objektu, který je přidělován nebo uvolňován, může být funkce přidělení podle velikosti vhodná k nahrazení vašeho vlastního kódu fondu paměti. Můžete se zbavit funkcí umístění a použít pouze vlastní operátor se dvěma argumenty
deletemísto funkcí umístění.Pokud nechcete kód okamžitě aktualizovat, můžete se vrátit ke starému chování pomocí možnosti
/Zc:sizedDealloc-kompilátoru . Pokud použijete tuto možnost, funkce delete se dvěma argumenty neexistují a nezpůsobí konflikt s operátorem placement delete.Datové členy unie
Členové unie již nemohou mít odkazové typy. Následující kód byl úspěšně zkompilován v sadě Visual Studio 2013, ale v sadě Visual Studio 2015 dojde k chybě.
union U1 { const int i; }; union U2 { int & i; }; union U3 { struct { int & i; }; };Předchozí kód generuje následující chyby:
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 typePokud chcete tento problém vyřešit, změňte odkazové typy buď na ukazatel, nebo na hodnotu. Změna typu na ukazatel vyžaduje změny v kódu, který používá sjednocovací pole. Změna kódu na hodnotu by změnila data uložená ve sjednocení, což má vliv na jiná pole, protože pole v typech sjednocení sdílejí stejnou paměť. V závislosti na velikosti hodnoty se může také změnit velikost unie.
Anonymní sjednocení jsou nyní více v souladu se standardem. Předchozí verze kompilátoru generovaly explicitní konstruktor a destruktor pro anonymní unie. Tyto funkce generované kompilátorem se odstraní v sadě Visual Studio 2015.
struct S { S(); }; union { struct { S s; }; } u; // C2280Předchozí kód vygeneruje v sadě Visual Studio 2015 následující chybu:
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>' herePokud chcete tento problém vyřešit, zadejte vlastní definice konstruktoru nebo destruktoru.
struct S { // Provide a default constructor by adding an empty function body. S() {} }; union { struct { S s; }; } u;Sjednocení s anonymními strukturami
Aby bylo možné splňovat standard, chování modulu runtime se změnilo pro členy anonymních struktur v sjednoceních. Konstruktor pro anonymní členy struktury v unii již není implicitně volán při vytvoření takové unie. Také destruktor pro anonymní členy struktury v unii se již implicitně nevolá, když unie přejde mimo rozsah. Vezměte v úvahu následující kód, ve kterém sjednocení U obsahuje anonymní strukturu, která obsahuje pojmenovanou členskou strukturu S, která má destruktor.
#include <stdio.h> struct S { S() { printf("Creating S\n"); } ~S() { printf("Destroying S\n"); } }; union U { struct { S s; }; U() {} ~U() {} }; void f() { U u; // Destructor implicitly called here. } int main() { f(); char s[1024]; printf("Press any key.\n"); gets_s(s); return 0; }Ve Visual Studio 2013 se při vytvoření unionu volá konstruktor pro S a při uvolnění zásobníku pro funkci f se volá destruktor pro S. V sadě Visual Studio 2015 se ale konstruktor a destruktor nevolají. Kompilátor zobrazí upozornění na tuto změnu chování.
warning C4587: 'U::s': behavior change: constructor is no longer implicitly calledwarning C4588: 'U::s': behavior change: destructor is no longer implicitly calledChcete-li obnovit původní chování, dejte anonymní struktuře název. Chování modulu runtime neanonymních struktur je stejné bez ohledu na verzi kompilátoru.
#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; }Případně zkuste přesunout kód konstruktoru a destruktoru do nových funkcí a zavolat tyto funkce z konstruktoru a destruktoru pro unii.
#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; }Rozlišení šablon
Byly provedeny změny v rozlišování názvů pro šablony. V jazyce C++ může při zvažování kandidátů na rozlišení jména dojít k tomu, že jedno nebo více jmen, která jsou zvažovaná jako potenciální shody, vytvoří neplatnou instanci šablony. Tyto neplatné instance obvykle nezpůsobují chyby kompilátoru, princip označovaný jako SFINAE (selhání nahrazení není chyba).
Pokud teď SFINAE vyžaduje, aby kompilátor vytvořil instanci specializace šablony třídy, všechny chyby, ke kterým dojde během tohoto procesu, jsou chyby kompilátoru. V předchozích verzích by kompilátor takové chyby ignoroval. Představte si například následující kód:
#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); }Pokud kompilujete s aktuálním kompilátorem, zobrazí se následující chyba:
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 ]Důvodem je to, že v okamžiku prvního vyvolání is_base_of třída
Dještě nebyla definována.V tomto případě je oprava nepoužívat takové vlastnosti typu, dokud není definována třída. Pokud přesunete definice
Bsouboru kódu aDna začátek souboru kódu, chyba se vyřeší. Pokud jsou definice v souborech hlaviček, zkontrolujte pořadí příkazů include pro soubory hlaviček a ujistěte se, že jsou všechny definice tříd zkompilovány před tím, než se použijí problematické šablony.Konstruktory kopírování
Ve verzích Visual Studio 2013 i 2015 kompilátor vygeneruje kopírovací konstruktor pro třídu, pokud má tato třída konstruktor přesunu definovaný uživatelem, ale žádný kopírovací konstruktor definovaný uživatelem. V Dev14 je tento implicitně vygenerovaný konstruktor kopírování označen také jako "= delete".
main deklarovaný jako extern "C" nyní vyžaduje návratový typ.
Následující kód teď vytvoří C4430.
extern "C" __cdecl main(){} // C4430Pokud chcete chybu opravit, přidejte návratový typ:
extern "C" int __cdecl main(){} // OKParametr typename není v inicializátoru člena povolený.
Následující kód teď vytvoří C2059:
template<typename T> struct S1 : public T::type { S1() : typename T::type() // C2059 { } }; struct S2 { typedef S2 type; }; S1<S2> s;Pokud chcete chybu opravit, odeberte
typenameji z inicializátoru:S1() : T::type() // OK ...Třída úložiště u explicitních specializace se ignoruje.
V následujícím kódu je specifikátor třídy statického úložiště ignorován.
template <typename T> void myfunc(T h) { } template<> static void myfunc(double h) // static is ignored { }Konstanta použitá v static_assert uvnitř šablony třídy vždy selže.
Následující kód způsobí, že
static_assertvždy selže:template <size_t some_value> struct S1 { static_assert(false, "default not valid"); // always invoked }; //other partial specializations hereChcete-li tento problém vyřešit, zabalte hodnotu do
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 herePravidla vynucená pro předávání deklarací (Platí pouze pro C.)
Následující kód teď vytvoří C2065:
struct token_s; typedef int BOOL; typedef int INT; typedef int(*PFNTERM)(PTOKEN, BOOL, INT); // C2065: 'PTOKEN' : undeclared identifierChcete-li tento problém vyřešit, přidejte správné předávací deklarace:
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);Konzistentnější vynucování typů ukazatelů funkcí
Následující kód teď vytvoří C2197:
typedef int(*F1)(int); typedef int(*F2)(int, int); void func(F1 f, int v1, int v2) { f(v1, v2); // C2197 }Nejednoznačná volání přetížených funkcí
Následující kód nyní vyvolá chybu C266: "N::bind": nejednoznačné volání přetížené funkce.
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 } };Chcete-li chybu opravit, můžete plně kvalifikovat volání na
bind: N::bind(...). Pokud je však tato změna manifestována prostřednictvím nelarovaného identifikátoru (C2065), může být vhodné tuto změnu opravit pomocíusingdeklarace.K tomuto vzoru často dochází u ComPtr a dalších typů v
Microsoft::WRLoboru názvů.Oprava nesprávné adresy
Následující kód vyvolá chybu C2440: '=': nelze převést 'type *' na 'type'. Chybu opravíte tak, že změníte &(typ) na (typ) a (&f()) na (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()); }Řetězcový literál je konstantní pole.
Následující kód nyní vytvoří C2664: 'void f(void )': nemůže převést argument 1 z const char ()[2] na void *.
void f(void *); void h(void) { f(&__FUNCTION__); void *p = &""; }Pokud chcete chybu opravit, změňte typ parametru funkce na
const void*, nebo změňte texthtak, aby vypadal takto:void h(void) { char name[] = __FUNCTION__; f( name); void *p = &""; }Řetězce UDL C++11
Následující kód nyní vytvoří chybu C3688: neplatná přípona literálu 'L'; literálový operátor nebo šablona literálového operátoru 'operátor ""L' nebyla nalezena.
#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"); }Pokud chcete chybu opravit, změňte kód tak, aby přidal mezeru:
#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"); }V předchozím
MACROpříkladu už není analyzován jako dva tokeny (řetězec následovaný makrem). Nyní se to analyzuje jako jeden token UDL. Totéž platí pro L"L", který byl analyzován dříve jako L a L" a nyní je analyzován jako L a "".Pravidla zřetězení řetězců byla rovněž přenesena do souladu se standardem, což znamená, že L"a" "b" je ekvivalentní L"ab". Předchozí edice sady Visual Studio nepřijaly zřetězení řetězců s jinou šířkou znaků.
Odebrání prázdného znaku v C++11
Následující kód nyní generuje chybu C2137: prázdná znaková konstanta
bool check(wchar_t c){ return c == L''; //implicit null character }Pokud chcete chybu opravit, změňte kód tak, aby explicitně zobrazoval hodnotu null:
bool check(wchar_t c){ return c == L'\0'; }Výjimky MFC nelze zachytit hodnotou, protože nejsou kopírovatelné.
Následující kód v aplikaci MFC nyní způsobuje chybu C2316: "D": nelze zachytit, protože destruktor a/nebo kopírovací konstruktor jsou nepřístupné nebo odstraněné.
struct B { public: B(); private: B(const B &); }; struct D : public B { }; int main() { try { } catch (D) // C2316 { } }Pokud chcete kód opravit, můžete blok catch změnit na
catch (const D &), ale lepším řešením je obvykle použít makra MFC TRY/CATCH.alignofje teď klíčové slovo.Následující kód nyní vytvoří chybu C2332: class: chybějící název značky. Chcete-li opravit kód, musíte přejmenovat třídu nebo, pokud třída provádí stejnou práci jako
alignof, stačí nahradit třídu novým klíčovým slovem.class alignof{}constexprje teď klíčové slovo.Následující kód nyní generuje chybu C2059: syntaktická chyba: ')'. Chcete-li opravit kód, musíte přejmenovat všechny názvy funkcí nebo proměnných, které jsou volána
constexpr.int constexpr() {return 1;}Pohyblivé typy nemohou být const
Pokud funkce vrátí typ, který má být přesunut, jeho návratový typ by neměl být
const.Odstraněné konstruktory kopírování
Následující kód nyní vytvoří C2280 S::S(S &&): pokouší se odkazovat na odstraněnou funkci:
struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = S(2, 3); //C2280Pokud chcete chybu opravit, použijte přímou inicializaci pro
S2:struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = {2,3}; //OKPřevod na ukazatel funkce se vygeneruje pouze v případě, že se nezachytí lambda
Následující kód vytvoří C2664 v sadě Visual Studio 2015.
void func(int(*)(int)) {} int main() { func([=](int val) { return val; }); }Pokud chcete chybu opravit, odeberte
=ze seznamu zachycení.Nejednoznačná volání zahrnující operátory převodu
Následující kód nyní generuje chybu C2440: Přetypování typu: nelze převést z S2 na S1:
struct S1 { S1(int); }; struct S2 { operator S1(); operator int(); }; void f(S2 s2) { (S1)s2; }Pokud chcete chybu opravit, explicitně volejte operátor převodu:
void f(S2 s2) { //Explicitly call the conversion operator s2.operator S1(); // Or S1((int)s2); }Následující kód nyní vytvoří chybu C2593: operátor =je nejednoznačný:
struct S1 {}; struct S2 { operator S1&(); operator S1() const; }; void f(S1 *p, S2 s) { *p = s; }Pokud chcete chybu opravit, explicitně volejte operátor převodu:
void f(S1 *p, S2 s) { *p = s.operator S1&(); }Oprava neplatné inicializace kopírování při inicializaci nestatického datového člena (NSDMI)
Následující kód nyní generuje chybu C2664: S1::S1(S1 &&): Nemůže převést argument 1 z logické hodnoty na const S1 &:
struct S1 { explicit S1(bool); }; struct S2 { S1 s2 = true; // error };Pokud chcete chybu opravit, použijte přímou inicializaci:
struct S2 { S1 s1{true}; // OK };Přístup k konstruktorům uvnitř příkazů decltype
Následující kód nyní vytvoří C2248: S::S: nemůže získat přístup k privátnímu členu deklarovanému ve třídě S:
class S { S(); public: int i; }; class S2 { auto f() -> decltype(S().i); };Chybu opravíte přidáním deklarace přítele pro
S2vS.class S { S(); friend class S2; // Make S2 a friend public: int i; };Výchozí konstruktor lambda se implicitně odstraní.
Následující kód nyní generuje chybu C3497: Nelze vytvořit instanci lambda:
void func(){ auto lambda = [](){}; decltype(lambda) other; }Chcete-li chybu opravit, odeberte povinnost volání výchozího konstruktoru. Pokud lambda nic nezachytí, může se přetypovat na ukazatel funkce.
Lambdas s odstraněným operátorem přiřazení
Následující kód nyní vytvoří chybu 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); }Pokud chcete chybu opravit, nahraďte lambda třídou functoru nebo odeberte potřebu použití operátoru přiřazení.
Pokus o přesunutí objektu s odstraněným konstruktorem kopírování
Následující kód nyní generuje chybu C2280: moveable::moveable(const moveable &): pokus o odkaz na odstraněnou funkci
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; };Pokud chcete chybu opravit, použijte
std::movemísto toho:S(moveable && m) : m_m(std::move(m))Místní třída nemůže odkazovat na jinou místní třídu definovanou později ve stejné funkci.
Následující kód nyní generuje chybu C2079: "s" používá nedefinovanou strukturu main::S2.
int main() { struct S2; struct S1 { void f() { S2 s; } }; struct S2 {}; }Chybu opravíte tak, že přesunete definici
S2:int main() { struct S2 { //moved up }; struct S1 { void f() { S2 s; } }; }Nelze volat chráněný základní ctor v těle odvozeného ctoru.
Následující kód nyní generuje chybu C2248: S1::S1: Nemůže získat přístup k chráněnému členu deklarovanému ve třídě S1.
struct S1 { protected: S1(); }; struct S2 : public S1 { S2() { S1(); } };Pokud chcete chybu opravit,
S2odeberte voláníS1()z konstruktoru a v případě potřeby ji vložte do jiné funkce.{} zabraňuje převodu na ukazatel
Následující kód nyní vytvoří C2439 S::p: člen nelze inicializovat.
struct S { S() : p({ 0 }) {} void *p; };Pokud chcete chybu opravit, odstraňte složené závorky kolem
0nebo jednoduše použijtenullptr, jak je znázorněno v tomto příkladu:struct S { S() : p(nullptr) {} void *p; };Nesprávná definice a použití makra s kulatými závorkami
Následující příklad nyní vygeneruje chybu C2008: ;: neočekávaná v definici makra
#define A; //cause of error struct S { A(); // error };Pokud chcete tento problém vyřešit, změňte horní čáru na
#define A();Následující kód vytvoří chybu C2059: syntaktická chyba: ')'
//notice the space after 'A' #define A () ; struct S { A(); };Pokud chcete kód opravit, odeberte mezeru mezi A a ().
Následující kód způsobí chybu C2091: funkce vrátí funkci:
#define DECLARE void f() struct S { DECLARE(); };Chcete-li chybu opravit, odeberte závorky za deklarací v S:
DECLARE;.Následující kód způsobí chybu C2062: typ int neočekávaně.
#define A (int) struct S { A a; };Pokud chcete tento problém vyřešit, definujte
Aho takto:#define A intExtra parens v deklaracích
Následující kód způsobí chybu C2062: typ int neočekávaně.
struct S { int i; (int)j; };Chcete-li chybu opravit, odeberte závorky kolem
j. Pokud jsou závorky potřeba k přehlednosti, použijtetypedef.Konstruktory generované kompilátorem a __declspec(novtable)
V sadě Visual Studio 2015 existuje větší pravděpodobnost, že kompilátor generované vložené konstruktory abstraktních tříd s virtuálními základními třídami mohou vystavit nesprávné použití
__declspec(novtable)při použití v kombinaci s__declspec(dllimport).Auto vyžaduje v přímé inicializaci seznamu jeden výraz.
Následující kód nyní vytvoří chybu C3518: 'testPositions': v kontextu přímé inicializace seznamu lze typ pro 'auto' odvodit pouze z jednoho výrazu inicializátoru.
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} };Pokud chcete chybu opravit, jednou z možností je inicializace
testPositionsnásledujícím způsobem: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} };Kontrola typů a ukazatelů na typy pro is_convertible
Následující kód nyní způsobí selhání statického tvrzení.
struct B1 { private: B1(const B1 &); }; struct B2 : public B1 {}; struct D : public B2 {}; static_assert(std::is_convertible<D, B2>::value, "fail");Pokud chcete chybu opravit, změňte
static_asserttak, aby porovnával ukazatele naDaB2:static_assert(std::is_convertible<D*, B2*>::value, "fail");deklarace __declspec(novtable) musí být konzistentní
__declspecdeklarace musí být konzistentní ve všech knihovnách. Následující kód teď vytvoří porušení pravidla odr (one-definition rule)://a.cpp class __declspec(dllexport) A { public: A(); A(const A&); virtual ~A(); private: int i; }; A::A() {} A::~A() {} A::A(const A&) {} //b.cpp // compile with cl.exe /nologo /LD /EHsc /Osx b.cpp #pragma comment(lib, "A") class __declspec(dllimport) A { public: A(); A(const A&); virtual ~A(); private: int i; }; struct __declspec(novtable) __declspec(dllexport) B : virtual public A { virtual void f() = 0; }; //c.cpp #pragma comment(lib, "A") #pragma comment(lib, "B") class __declspec(dllimport) A { public: A(); A(const A&); virtual ~A(); private: int i; }; struct /* __declspec(novtable) */ __declspec(dllimport) B // Error. B needs to be novtable here also. : virtual public A { virtual void f() = 0; }; struct C : virtual B { virtual void f(); }; void C::f() {} C c;
Vylepšení shody v aktualizaci Update 1
Privátní virtuální základní třídy a nepřímá dědičnost
Předchozí verze kompilátoru umožnily odvozené třídě volat členské funkce jeho nepřímo odvozené
private virtualzákladní třídy. Toto staré chování bylo nesprávné a neodpovídá standardu C++. Kompilátor už nepřijímá kód napsaný tímto způsobem a v důsledku toho vydává chybu kompilátoru C2280.error C2280: 'void *S3::__delDtor(unsigned int)': attempting to reference a deleted functionPříklad (před)
class base { protected: base(); ~base(); }; class middle : private virtual base {}; class top : public virtual middle {}; void destroy(top *p) { delete p; // }Příklad (po)
class base; // as above class middle : protected virtual base {}; class top : public virtual middle {}; void destroy(top *p) { delete p; }- nebo -
class base; // as above class middle : private virtual base {}; class top : public virtual middle, private virtual bottom {}; void destroy(top *p) { delete p; }Přetížený operátor new a operátor delete
Předchozí verze kompilátoru umožňovaly, aby nečlenové operátor new a operator delete byly deklarovány jako statické a deklarovány v jiných oborech názvů než v globálním oboru názvů. Toto staré chování vytvářelo riziko, že program nebude volat implementaci operátora
newnebodelete, kterou zamýšlel programátor, což mohlo vést k tichému nesprávnému chování během běhu programu. Kompilátor už nepřijímá kód napsaný tímto způsobem a místo toho vydává chybu kompilátoru 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.Příklad (před)
static inline void * __cdecl operator new(size_t cb, const std::nothrow_t&) // error C2323Příklad (po)
void * __cdecl operator new(size_t cb, const std::nothrow_t&) // removed 'static inline'Kromě toho, i když kompilátor neposkytuje konkrétní diagnostiku, vložený operátor
newse považuje za špatně vytvořený.Volání operátoru type() (převod definovaný uživatelem) u jiných typů než tříd
Předchozí verze kompilátoru umožňovaly volat "operator type()" u typů, které nejsou třídami, přičemž to tiše ignoroval. Toto staré chování vytvořilo riziko tichého špatného generování kódu, což vedlo k nepředvídatelným chování modulu runtime. Kompilátor už nepřijímá kód napsaný tímto způsobem a místo toho vydává chybu kompilátoru C2228.
error C2228: left of '.operator type' must have class/struct/unionPříklad (před)
typedef int index_t; void bounds_check(index_t index); void login(int column) { bounds_check(column.operator index_t()); // error C2228 }Příklad (po)
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' }Redundantní název typu v propracovaných specifikátorech typů
Předchozí verze kompilátoru umožňovaly
typenameve specifikátoru detailního typu, ale kód napsaný tímto způsobem je sémanticky nesprávný. Kompilátor už nepřijímá kód napsaný tímto způsobem a místo toho vydává chybu kompilátoru C3406.error C3406: 'typename' cannot be used in an elaborated type specifierPříklad (před)
template <typename class T> class container;Příklad (po)
template <class T> // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case class container;Odedukování typu pole ze seznamu inicializátorů
Předchozí verze kompilátoru nepodporují odpočty typů polí ze seznamu inicializátorů. Kompilátor teď podporuje tuto formu odpočtu typů a v důsledku toho může být volání šablon funkcí pomocí seznamů inicializátorů nejednoznačné nebo může být zvoleno jiné přetížení než v předchozích verzích kompilátoru. Chcete-li tyto problémy vyřešit, program teď musí explicitně určit přetížení zamýšlené programátorem.
Když toto nové chování způsobí řešení přetížení zvážit další kandidáta, který je stejně dobrý jako historický kandidát, volání se stane nejednoznačným a kompilátor vydá chybu kompilátoru C2668 jako výsledek.
error C2668: 'function' : ambiguous call to overloaded function.Příklad 1: Nejednoznačné volání přetížené funkce (před)
// 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 }Příklad 1: nejednoznačné volání přetížené funkce (následně)
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); }Když toto nové chování způsobí, že při řešení přetížení je uvažován další kandidát, který lépe odpovídá než historický kandidát, volání se jednoznačně vyřeší na nového kandidáta, což způsobí změnu chování programu, která se pravděpodobně odlišuje od toho, co programátor zamýšlel.
Příklad 2: změna rozlišení přetížení (před)
// 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 }); }Příklad 2: změna vyhodnocení přetížení (po)
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 }); }Obnovení upozornění příkazu switch
Předchozí verze kompilátoru odebrala některá upozornění související s
switchpříkazy. Tato upozornění se teď obnovila. Kompilátor nyní vydává obnovená varování a varování související s konkrétními případy (včetně výchozího případu) jsou nyní vydána na řádku obsahujícím problematický případ, nikoli na posledním řádku switch výrazu. V důsledku toho, že nyní tato upozornění vydáváte na různých řádcích než v minulosti, upozornění, která byla dříve potlačena použitím#pragma warning(disable:####), už nemusí být potlačena tak, jak má. Chcete-li tato upozornění potlačit, jak bylo zamýšleno, může být nutné přesunout direktivu#pragma warning(disable:####)na řádek nad prvním případem chyby. Toto jsou obnovená upozornění: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 givenPříklad C4063 (před)
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; } }Příklad C4063 (po)
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; } };Příklady dalších obnovených upozornění jsou uvedeny v jejich dokumentaci.
#include: použití specifikátoru rodičovského adresáře .. v názvu cesty (týká se pouze
/Wall/WX)Předchozí verze kompilátoru nezjistily použití specifikátoru nadřazeného adresáře .. v cestě direktiv
#include. Kód napsaný tímto způsobem je obvykle určen k zahrnutí hlaviček, které existují mimo projekt nesprávným použitím cest relativních k projektu. Toto staré chování vytvořilo riziko, že program může být kompilován zahrnutím jiného zdrojového souboru, než je zamýšlený programátor, nebo že tyto relativní cesty nebudou přenosné do jiných prostředí sestavení. Kompilátor teď rozpozná a upozorní programátora na kód napsaný tímto způsobem a v případě povolení vydá volitelné upozornění kompilátoru C4464.warning C4464: relative include path contains '..'Příklad (před)
#include "..\headers\C4426.h" // emits warning C4464Příklad (po)
#include "C4426.h" // add absolute path to 'headers\' to your project's include directoriesKromě toho, i když kompilátor neposkytuje konkrétní diagnostiku, doporučujeme, aby specifikátor nadřazeného adresáře "." neměl být použit k určení adresářů zahrnutí projektu.
#pragma optimize() přesahuje konec souboru hlavičky (pouze ovlivňuje
/Wall/WX)Předchozí verze kompilátoru nedetekovaly změny nastavení příznaků optimalizace, které uniknou z hlavičkového souboru, jenž je zahrnut v překladové jednotce. Kompilátor nyní detekuje a upozorní programátora na kód napsaný tímto způsobem a v případě povolení vydá volitelné varování kompilátoru C4426 v místě chybného
#include. Toto upozornění se vydává pouze v případě, že změny kolidují s příznaky optimalizace nastavené argumenty příkazového řádku kompilátoru.warning C4426: optimization flags changed after including header, may be due to #pragma optimize()Příklad (před)
// C4426.h #pragma optimize("g", off) ... // C4426.h ends // C4426.cpp #include "C4426.h" // warning C4426Příklad (po)
// 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"Neshoda #pragma warning(push) a #pragma warning(pop) (ovlivňuje pouze
/Wall/WX)Předchozí verze kompilátoru nezjistily
#pragma warning(push)změny stavu spárované se#pragma warning(pop)změnami stavu v jiném zdrojovém souboru, který je zřídka zamýšlený. Toto staré chování vytvořilo riziko, že program bude zkompilován s jinou sadou povolených upozornění, než programátor zamýšlel, což může v tichosti vést ke špatnému chování běhového prostředí. Kompilátor nyní rozpozná a upozorní programátora na kód napsaný tímto způsobem a vydá volitelné upozornění kompilátoru C5031 v umístění odpovídajícího#pragma warning(pop), pokud je povoleno. Toto upozornění obsahuje poznámku odkazující na umístění odpovídajícího #pragma warning(push).warning C5031: #pragma warning(pop): likely mismatch, popping warning state pushed in different filePříklad (před)
// 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 ...Příklad (po)
// 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" ...Ačkoli vzácně, je kód napsaný tímto způsobem někdy úmyslný. Kód napsaný tímto způsobem je citlivý na změny v
#includepořadí. Pokud je to možné, doporučujeme, aby soubory zdrojového kódu spravovaly stav upozornění samostatně.Nedostupné #pragma upozornění (nabízení) (pouze ovlivňuje
/Wall/WX)Předchozí verze kompilátoru nedokázaly detekovat nesrovnalosti změn stavu
#pragma warning(push)na konci překladové jednotky. Kompilátor nyní rozpozná a upozorní programátora na kód napsaný tímto způsobem a vydá volitelné upozornění kompilátoru C5032 na místě, kde se vyskytuje nesoulad s#pragma warning(push), pokud je povoleno. Toto upozornění se vydává pouze v případě, že v jednotce překladu nejsou žádné chyby kompilace.warning C5032: detected #pragma warning(push) with no corresponding #pragma warning(pop)Příklad (před)
// 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.hPříklad (následující)
// 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)V důsledku vylepšeného sledování stavu upozornění #pragma mohou být vydána další upozornění.
Předchozí verze kompilátoru sledovaly změny stavu upozornění #pragma nedostatečně dobře k tomu, aby vydaly všechna zamýšlená upozornění. Toto chování vytvořilo riziko, že určitá upozornění by byla účinně potlačena za jiných okolností, než jaké zamýšlel programátor. Kompilátor nyní sleduje
#pragma warningstav robustněji – zejména související se#pragma warningzměnami stavu uvnitř šablon – a volitelně vydává nová upozornění C5031 a C5032, které jsou určeny k tomu, aby programátoru pomohl najít nezamýšlené použití#pragma warning(push)a#pragma warning(pop).V důsledku vylepšeného
#pragma warningsledování změn stavu mohou být nyní vydána upozornění, která byla dříve nesprávně potlačována, nebo upozornění související s problémy, které byly dříve chybně diagnostikovány.Vylepšená identifikace nedostupného kódu
Změny standardní knihovny jazyka C++ a vylepšená schopnost volání vložených funkcí v předchozích verzích kompilátoru může kompilátoru umožnit prokázat, že určitý kód je nyní nedostupný. Toto nové chování může vést k novým a častěji vydávaným instancím upozornění C4720.
warning C4720: unreachable codeV mnoha případech může být toto upozornění vydáno pouze při kompilaci s povolenými optimalizacemi, protože optimalizace můžou vyřaizovat více volání funkcí, eliminovat redundantní kód nebo jinak zajistit, že určitý kód je nedostupný. Zjistili jsme, že nové instance upozornění C4720 se často vyskytly v blocích try/catch , zejména v souvislosti s použitím příkazu std::find.
Příklad (před)
try { auto iter = std::find(v.begin(), v.end(), 5); } catch (...) { do_something(); // ok }Příklad (po)
try { auto iter = std::find(v.begin(), v.end(), 5); } catch (...) { do_something(); // warning C4702: unreachable code }
Vylepšení shody v aktualizaci Update 2
V důsledku částečné podpory výrazu SFINAE mohou být vydána další upozornění a chyby.
Předchozí verze kompilátoru neanalyzovali určité druhy výrazů uvnitř
decltypespecifikátorů kvůli nedostatku podpory výrazu SFINAE. Toto staré chování bylo nesprávné a neodpovídá standardu C++. Kompilátor teď tyto výrazy parsuje a má částečnou podporu výrazu SFINAE kvůli probíhajícím vylepšením shody. Kompilátor proto nyní vydává upozornění a chyby zjištěné ve výrazech, které předchozí verze kompilátoru neanalyly.Když toto nové chování analyzuje
decltypevýraz, který obsahuje typ, který ještě nebyl deklarován, kompilátor vydá chybu kompilátoru C2039 jako výsledek.error C2039: 'type': is not a member of 'global namespace'Příklad 1: použití nedelarovaného typu (před)
struct s1 { template < typename T> auto f() - > decltype(s2< T> ::type::f()); // error C2039 template< typename> struct s2 {}; }Příklad 1 (poté)
struct s1 { template < typename> // forward declare s2struct s2; template < typename T> auto f() - > decltype(s2< T> ::type::f()); template< typename> struct s2 {}; }Když toto nové chování analyzuje
decltypevýraz, ve kterém chybí nezbytné použití klíčového slovatypenamek označení, že závislý název je typ, kompilátor vydá upozornění kompilátoru C4346 společně s chybou kompilátoru 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'Příklad 2: Závislý název není typem (před)
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 };Příklad 2 (po)
template < typename T> struct s1 { ... }; // as above template < typename T> struct s2 { ... }; // as above template < typename T> T declval(); struct s { template < typename T> auto f(T t) - > decltype(t(declval< S1< typename S2< T> ::type> ::type> ())); };volatilečlenské proměnné brání implicitně definovaným konstruktorům a operátorům přiřazení.Předchozí verze kompilátoru povolily třídu, která má
volatilečlenské proměnné, aby byly automaticky generovány výchozí konstruktory kopírování/přesunutí a výchozí operátory přiřazení kopírování/přesunutí. Toto staré chování bylo nesprávné a neodpovídá standardu C++. Kompilátor nyní považuje třídu, která má členské proměnnévolatile, za třídu s netriviálními operátory konstrukce a přiřazení, což brání automatickému generování výchozích implementací těchto operátorů. Pokud je taková třída členem sjednocení (nebo anonymní sjednocení uvnitř třídy), konstruktory kopírování/přesunutí a operátory přiřazení kopírování/přesunutí sjednocení (nebo třídy obsahující anonymní sjednocení) budou implicitně definovány jako odstraněné. Pokus o vytvoření nebo zkopírování sjednocení (nebo třídy obsahující anonymní sjednocení) bez explicitního definování je chyba a kompilátor vydává chybu kompilátoru C2280 v důsledku toho.error C2280: 'B::B(const B &)': attempting to reference a deleted functionPříklad (před)
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 C2280Příklad (po)
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 C2280Statické členské funkce nepodporují cv-kvalifikátory.
Předchozí verze sady Visual Studio 2015 umožňovaly statické členské funkce mít kvalifikátory cv. Toto chování je způsobeno regresí v sadě Visual Studio 2015 a Visual Studio 2015 Update 1; Visual Studio 2013 a předchozí verze kompilátoru zamítají kód napsaný tímto způsobem. Chování sady Visual Studio 2015 a Visual Studio 2015 Update 1 je nesprávné a neodpovídá standardu C++. Visual Studio 2015 Update 2 odmítne kód napsaný tímto způsobem a místo toho vydá chybu kompilátoru C2511.
error C2511: 'void A::func(void) const': overloaded member function not found in 'A'Příklad (před)
struct A { static void func(); }; void A::func() const {} // C2511Příklad(po)
struct A { static void func(); }; void A::func() {} // removed constPředběžná deklarace výčtu není v kódu WinRT povolena (pouze ovlivňuje
/ZW)Kód zkompilovaný pro prostředí Windows Runtime (WinRT) neumožňuje předsazení deklarace typů pomocí
enum, podobně jako při kompilaci spravovaného kódu C++ pro rozhraní .Net Framework s použitím přepínače kompilátoru/clr. Toto chování zajišťuje, že velikost výčtu je vždy známá a lze ji správně promítat do systému typů WinRT. Kompilátor odmítne kód napsaný tímto způsobem a vydá chybu kompilátoru C2599 společně s chybou kompilátoru C3197.error C2599: 'CustomEnum': the forward declaration of a WinRT enum is not allowederror C3197: 'public': can only be used in definitionsPříklad (před)
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; } };Příklad (po)
// forward declaration of CustomEnum removed namespace A { public enum class CustomEnum : int32 { Value1 }; } public ref class Component sealed { public: CustomEnum f() { return CustomEnum::Value1; } };Přetížený nečlenský operátor new a operátor delete nemusí být deklarovány jako inline (úroveň 1 (
/W1) ve výchozím nastavení).Předchozí verze kompilátoru nevydávají upozornění, pokud jsou operátory new a delete, které nejsou členy, deklarovány inline. Kód napsaný tímto způsobem je nesprávně utvořený (není požadována diagnostika) a může způsobit problémy s pamětí způsobené nesouhlasem mezi operátory new a delete (zejména při použití společně s alokací velikosti), které může být obtížné diagnostikovat. Kompilátor teď vydává upozornění kompilátoru C4595, aby pomohl identifikovat kód napsaný tímto způsobem.
warning C4595: 'operator new': non-member operator new or delete functions may not be declared inlinePříklad (před)
inline void* operator new(size_t sz) // warning C4595 { ... }Příklad (po)
void* operator new(size_t sz) // removed inline { ... }Oprava kódu napsaného tímto způsobem může vyžadovat, aby definice operátorů byly přesunuty z hlavičkového souboru a do odpovídajícího zdrojového souboru.
Vylepšení shody v aktualizaci Update 3
std::is_convertable teď detekuje vlastní přiřazení (standardní knihovna).
Předchozí verze vlastnosti typu
std::is_convertablenezjistily správně samopřiřazení typu třídy, pokud je jeho kopírovací konstruktor odstraněn nebo soukromý. Nyní jestd::is_convertable<>::valuesprávně nastaven nafalsepři použití na typ třídy se smazaným nebo privátním konstruktorem kopírování.K této změně není přidružená žádná diagnostika kompilátoru.
Příklad
#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");V předchozích verzích kompilátoru statické aserce v dolní části tohoto příkladu projdou, protože byl
std::is_convertable<>::valuenesprávně nastaven natrue.std::is_convertable<>::valueNyní je správně nastaven nafalse, což způsobuje selhání statických asercí.Výchozí nebo odstraněné triviální kopírovací a přenosové konstruktory respektují specifikátory přístupu.
Předchozí verze kompilátoru neprováděly kontrolu přístupového specifikátoru výchozích nebo odstraněných triviálních konstruktorů kopírování a přesunutí před povolením jejich zavolání. Toto staré chování bylo nesprávné a neodpovídá standardu C++. V některých případech toto staré chování vytvořilo riziko tichého chybného generování kódu, což vede k nepředvídatelným chováním za běhu. Kompilátor teď zkontroluje specifikátor přístupu standardně nebo smazaně triviálních kopírovacích a přesunovacích konstruktorů, aby určil, zda může být volán, a pokud ne, vydá upozornění kompilátoru C2248.
error C2248: 'S::S' cannot access private member declared in class 'S'Příklad (před)
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 }Příklad (po)
class S { public: S() = default; private: S(const S&) = default; }; void f(const S&); // pass S by reference int main() { S s; f(s); }Vyřazení podpory kódu ATL s atributy (úroveň 1 (
/W1) ve výchozím nastavení)Předchozí verze kompilátoru podporovaly kód ATL s atributy. Jako další fáze odebrání podpory pro atributovaný kód ATL, který začal v sadě Visual Studio 2008, byl atributovaný kód ATL označen jako zastaralý. Kompilátor teď vydává upozornění kompilátoru C4467, aby pomohl identifikovat tento druh zastaralého kódu.
warning C4467: Usage of ATL attributes is deprecatedPokud chcete pokračovat v používání kódu ATL s atributy, dokud nebude podpora odebrána z kompilátoru, můžete toto upozornění zakázat předáním
/Wv:18/wd:4467argumentů příkazového řádku kompilátoru nebo přidáním#pragma warning(disable:4467)do zdrojového kódu.Příklad 1 (před)
[uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")] class A {};Příklad 1 (po)
__declspec(uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")) A {};Někdy možná budete potřebovat nebo chcete vytvořit soubor IDL, abyste se vyhnuli zastaralým atributům ATL, jako v ukázkovém kódu níže.
Příklad 2 (před)
[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 { // ... };Nejprve vytvořte soubor *.idl; vygenerovaný soubor vc140.idl lze použít k získání souboru *.idl obsahujícího rozhraní a poznámky.
Dále do sestavení přidejte krok MIDL, abyste měli jistotu, že se vygenerují definice rozhraní C++.
Příklad 2 IDL (za)
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; }; }Pak použijte ATL přímo v implementačním souboru, jak je znázorněno v ukázkovém kódu níže.
Příklad 2 Implementace (poté)
#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() };Předkompilované soubory hlaviček (PCH) a neshodované direktivy #include (pouze ovlivňuje
/Wall/WX)Předchozí verze kompilátoru přijímaly neshodné příkazy
#includeve zdrojových souborech mezi kompilacemi-Yca-Yupři použití předkompilovaných hlaviček (PCH). Kód napsaný tímto způsobem už kompilátor nepřijímá. Kompilátor teď vydává upozornění kompilátoru CC4598, které pomáhá identifikovat neshodované#includedirektivy při použití souborů PCH.warning C4598: 'b.h': included header file specified for Ycc.h at position 2 does not match Yuc.h at that positionPříklad (před):
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"Příklad (po)
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"Předkompilované soubory hlaviček (PCH) a nesprávné adresáře zahrnutí (pouze ovlivňuje
/Wall/WX)Předchozí verze kompilátoru akceptovaly neshodu, včetně argumentů příkazového řádku () adresáře (
-I) kompilátoru mezi-Yckompilacemi a-Yupři použití předkompilovaných souborů hlaviček (PCH). Kód napsaný tímto způsobem už kompilátor nepřijímá. Kompilátor nyní vydává upozornění kompilátoru CC4599, aby pomohl identifikovat nesouladné argumenty příkazového řádku pro adresář zahrnutí-I, když používáte soubory PCH.warning C4599: '-I..' : specified for Ycc.h at position 1 does not match Yuc.h at that positionPříklad (před)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h Z.cppPříklad (po)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h -I.. Z.cpp
Změny shody sady Visual Studio 2013
kompilátor
Poslední klíčové slovo teď vygeneruje nevyřešenou chybu symbolu, kde by se zkompilovala dříve:
struct S1 { virtual void f() = 0; }; struct S2 final : public S1 { virtual void f(); }; int main(S2 *p) { p->f(); }V dřívějších verzích nebyla vydána chyba, protože volání bylo
virtualvolání; přestože by ale program za běhu selhal. Nyní je vydána chyba linkeru, protože třída je známa jako konečná. V tomto příkladu chcete-li opravit chybu, byste měli propojit objekt, který obsahuje definiciS2::f.Při použití přátelských funkcí v oborech názvů je nutné tyto funkce znovu deklarovat před jejich použitím, jinak se zobrazí chyba, protože kompilátor teď odpovídá standardu ISO C++. Například tento příklad se už nekompiluje:
namespace NS { class C { void func(int); friend void func(C* const) {} }; void C::func(int) { NS::func(this); // error } }Chcete-li tento kód opravit, deklarujte
friendfunkci: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); }Standard C++ neumožňuje explicitní specializaci ve třídě. Přestože kompilátor jazyka Microsoft C++ umožňuje v některých případech, například v následujícím příkladu, je nyní vygenerována chyba, protože kompilátor nepovažuje druhou funkci za specializaci prvního.
template < int N> class S { public: template void f(T& val); template < > void f(char val); }; template class S< 1>;Chcete-li tento kód opravit, upravte druhou funkci:
template <> void f(char& val);Kompilátor se už nepokusí tyto dvě funkce v následujícím příkladu nejednoznačit a teď vygeneruje chybu:
template< typename T> void Func(T* t = nullptr); template< typename T> void Func(...); int main() { Func< int>(); // error }Chcete-li tento kód opravit, upřesněte volání:
template< typename T> void Func(T* t = nullptr); template< typename T> void Func(...); int main() { Func< int>(nullptr); // ok }Než kompilátor odpovídal standardu ISO C++11, následující kód by se zkompiloval a způsobil, že by se
xvyřešilo na typint:auto x = {0}; int y = x;Tento kód nyní vyřeší
xna typstd::initializer_list<int>a způsobí chybu na dalším řádku, když se pokusí přiřaditxk typuint. (Ve výchozím nastavení neexistuje žádný převod.) Chcete-li tento kód opravit, použijteintk nahrazeníauto:int x = {0}; int y = x;Agregační inicializace již není povolena, pokud typ hodnoty vpravo neodpovídá typu inicializované hodnoty vlevo a je vydána chyba, protože standard ISO C++11 vyžaduje jednotné inicializace, aby fungovala bez zužování převodů. Pokud byl dříve k dispozici zužující převod, by bylo místo chyby vydáno kompilátorové upozornění (úroveň 4) C4242.
int i = 0; char c = {i}; // errorChcete-li tento kód opravit, přidejte explicitní zužující převod:
int i = 0; char c = {static_cast<char>(i)};Následující inicializace už není povolená:
void *p = {{0}};Chcete-li tento kód opravit, použijte některou z těchto forem:
void *p = 0; // or void *p = {0};Vyhledávání názvů se změnilo. Následující kód se v kompilátoru C++ v sadě Visual Studio 2012 a Visual Studio 2013 vyřeší jinak:
enum class E1 { a }; enum class E2 { b }; int main() { typedef E2 E1; E1::b; }Ve Visual Studiu 2012 byl výraz
E1::bvyhodnocen na::E1v globálním oboru. Ve Visual Studiu 2013 seE1ve výrazuE1::břeší jakotypedef E2definice vmain()a má typ::E2.Změnilo se rozložení objektu. Na platformě x 64 se může v porovnání z předchozími verzemi změnit rozložení objektů třídy. Pokud má
virtualfunkci, ale nemá základní třídu, která mávirtualfunkci, objektový model kompilátoru vloží ukazatel navirtualtabulku funkcí za rozložení datového člena. To znamená, že rozložení nemusí být ve všech případech optimální. V předchozích verzích se optimalizace pro platformu x64 pokoušela vylepšit rozložení za vás, ale protože ve složitých situacích s kódem nefungovala správně, byla odebrána ve Visual Studio 2013. Podívejte se například na tento kód:__declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };Ve Visual Studio 2013 je výsledek
sizeof(S2)na x64 48, ale v předchozích verzích se hodnotil jako 32. Chcete-li provést toto vyhodnocení na hodnotu 32 v kompilátoru jazyka C++ sady Visual Studio 2013 pro x64, přidejte fiktivní základní třídu, která mávirtualfunkci:__declspec(align(16)) struct S1 { }; struct dummy { virtual ~dummy() {} }; struct S2 : public dummy { virtual ~S2(); void *p; S1 s; };Pokud chcete najít místa v kódu, která by se dřívější verze pokusila optimalizovat, použijte kompilátor z této verze společně s možností kompilátoru
/W3a zapněte upozornění C4370. Příklad:#pragma warning(default:4370) __declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };Před sadou Visual Studio 2013 tento kód vypíše tuto zprávu: "upozornění C4370: S2: rozložení třídy se změnilo z předchozí verze kompilátoru kvůli lepšímu balení".
Kompilátor x86 má stejný neoptimální problém s rozložením ve všech verzích kompilátoru. Pokud je například tento kód je zkompilován pro platformu x86:
struct S { virtual ~S(); int i; double d; };Výsledek
sizeof(S)je 24. Pokud ale použijete alternativní řešení uvedené pro platformu x64, můžete ho snížit na 16:struct dummy { virtual ~dummy() {} }; struct S : public dummy { virtual ~S(); int i; double d; };
Standardní knihovna
Kompilátor C++ v sadě Visual Studio 2013 detekuje neshody v _ITERATOR_DEBUG_LEVEL, které byly implementovány v sadě Visual Studio 2010 a neshody RuntimeLibrary. K těmto neshodám dochází, když jsou možnosti kompilátoru /MT (statická verze), /MTd (statické ladění), /MD (dynamická verze) a /MDd (dynamické ladění) smíšené.
Pokud váš kód uznává šablony simulovaných aliasů předchozí verze, musíte ho změnit. Například místo
allocator_traits<A>::rebind_alloc<U>::other, teď musíte říctallocator_traits<A>::rebind_alloc<U>. Přestožeratio_add<R1, R2>::typejiž není nutný a nyní doporučujeme použítratio_add<R1, R2>, stále se první zkompiluje, protožeratio<N, D>musí mít definován "typ" pro snížený poměr, což bude stejný typ, pokud již je snížen.Musíte použít
#include <algorithm>při volánístd::min()nebostd::max().Pokud váš stávající kód používá simulované výčty s oborem z předchozí verze – tradiční neskopové výčty zabalené v jmenných prostorech – musíte ho změnit. Pokud jste například odkazovali na typ
std::future_status::future_status, teď musíte říctstd::future_status. Většina kódu ale nemá vliv – napříkladstd::future_status::readyse stále kompiluje.explicit operator bool()je přísnější než operátor unspecified-bool-type().explicit operator bool()umožňuje explicitní konverze na bool – například pokud je dánoshared_ptr<X> sp, pak jsou oběstatic_cast<bool>(sp)abool b(sp)platné – a Boolean-testovatelné "kontextové konverze" na bool – napříkladif (sp),!sp,sp &&.explicit operator bool()však zakazuje implicitní převody na booleovskou hodnotu, takže nemůžete řícibool b = sp;a protože je návratový typ bool, nemůžete řícireturn sp.Teď, když jsou implementované skutečné variadické šablony, _VARIADIC_MAX a související makra nemají žádný vliv. Pokud stále definujete _VARIADIC_MAX, bude ignorován. Pokud jste uznali naše makrosystémy určené k podpoře simulovaných variadic šablon jakýmkoliv jiným způsobem, musíte změnit váš kód.
Kromě běžných klíčových slov teď hlavičky standardní knihovny jazyka C++ zakázaly nahrazení makra kontextově citlivých klíčových slov override a final.
reference_wrapper,ref(), acref()nyní zakazují vazbu na dočasné objekty.<random>nyní přísně vynucuje své předpoklady času kompilace.Různé vlastnosti standardní knihovny jazyka C++ mají předběžnou podmínku "T musí být úplný typ". Přestože kompilátor nyní tuto předběžnou podmínku vynucuje přísněji, nemusí ji vynutit ve všech situacích. (Vzhledem k tomu, že porušení předpokladů standardní knihovny C++ aktivují nedefinované chování, standard nezaručuje vynucení.)
Standardní knihovna C++ nepodporuje
/clr:oldSyntax.Specifikace C++11 pro
common_type<>měla neočekávané a nežádoucí důsledky; konkrétně způsobuje, žecommon_type<int, int>::typevracíint&&. Proto kompilátor implementuje návrh řešení problému 2141, který navrhla pracovní skupina pro knihovny, abycommon_type<int, int="">::typevraceloint.Jako vedlejší účinek této změny už případ identity nefunguje (
common_type<T>ne vždy vede k typuT). Toto chování odpovídá navrhovanému řešení, ale přeruší veškerý kód, který se spoléhal na předchozí chování.Pokud potřebujete atribut identity, nepoužívejte nestandardní
std::identity, definovaný v<type_traits>, neboť nebude fungovat pro<void>. Místo toho implementujte vlastní typovou vlastnost identity tak, aby vyhovovala vašim potřebám. Tady je příklad:template < typename T> struct Identity { typedef T type; };
MFC a ATL
Visual Studio 2013 Pouze: Knihovna MFC MBCS není součástí Visual Studio, protože Unicode je tak populární a použití kódování MBCS výrazně pokleslo. Tato změna také udržuje MFC lépe sladěné s Windows SDK, protože mnoho nových ovládacích prvků a zpráv je pouze pro Unicode. Pokud však budete muset i nadále používat knihovnu MFC MBCS, můžete ji stáhnout z webu Stažení softwaru společnosti Microsoft na vícebajtové knihovně MFC pro Visual Studio 2013. Distribuovatelný balíček Visual C++ stále zahrnuje i tuto knihovnu. (Poznámka: Knihovna MBCS DLL je součástí součástí instalačních komponent jazyka C++ v sadě Visual Studio 2015 a novějších verzích).
Přístupnost pásu karet MFC byla změněna. Místo jednoúrovňové architektury je teď hierarchická architektura. Staré chování můžete stále používat voláním
CRibbonBar::EnableSingleLevelAccessibilityMode().CDatabase::GetConnectmetoda je odebrána. Aby se zlepšilo zabezpečení, připojovací řetězec se teď ukládá zašifrovaný a dešifruje se jen podle potřeby; nelze ho vrátit jako prostý text. Řetězec lze získat pomocíCDatabase::Dumpmetody.CWnd::OnPowerBroadcastPodpis byl změněn. Definice tohoto zpracovatele zpráv byla změněna tak, aby přijal LPARAM jako druhý parametr.Podpisy jsou změněny, aby vyhovovaly zpracovatelům zpráv. Seznamy parametrů u následujících funkcí se změnily a používají nově přidané popisovače zpráv ON_WM_ *:
CWnd::OnDisplayChangezměněno na (UINT, int, int) místo (WPARAM, LPARAM), aby bylo možné nové makro ON_WM_DISPLAYCHANGE použít v mapě zpráv.CFrameWnd::OnDDEInitiatebyl změněn z (WPARAM, LPARAM) na (CWnd*, UINT, UINT), aby bylo možné v mapě zpráv použít nové makro ON_WM_DDE_INITIATE.CFrameWnd::OnDDEExecutebyla změněna z (WPARAM, LPARAM) na (CWnd*, HANDLE), aby bylo možné v mapě zpráv používat nové makro ON_WM_DDE_EXECUTE.CFrameWnd::OnDDETerminatebylo změněno na parametr typu (CWnd*) místo (WPARAM, LPARAM), aby bylo možné v mapě zpráv použít nové makro ON_WM_DDE_TERMINATE.CMFCMaskedEdit::OnCutzměna na žádné parametry místo (WPARAM, LPARAM), aby bylo možné nové ON_WM_CUT makro použít v mapě zpráv.CMFCMaskedEdit::OnClearzměna na žádné parametry místo (WPARAM, LPARAM), aby bylo možné nové ON_WM_CLEAR makro použít v mapě zpráv.CMFCMaskedEdit::OnPastezměněno na žádné parametry namísto (WPARAM, LPARAM), aby mohlo být nové makro ON_WM_PASTE použito v mapě zpráv.
#ifdefdirektivy v souborech hlaviček MFC jsou odebrány. V souborech hlaviček MFC souvisejících s nepodporovanými verzemi systému Windows (#ifdef) jsou odebrány různéWINVER < 0x0501direktivy.Knihovna DLL ATL (atl120.dll) se odebere. Knihovna ATL je nyní poskytována jako záhlaví a statická knihovna (atls.lib).
Atlsd.lib, atlsn.lib a atlsnd.lib jsou odebrány. Knihovna Atls.lib již nemá závislosti na znakové sadě ani kód specifický pro ladění/vydání. Protože princip funkce je stejný pro Unicode/ANSI i ladění/vydání, je vyžadována pouze jedna verze knihovny.
Nástroj ATL/MFC Trace je odstraněn společně s ATL DLL a mechanismus trasování byl zjednodušen. Konstruktor
CTraceCategorynyní přijímá jeden parametr (název kategorie) a makra TRACE volají funkce pro ladicí sestavy CRT.
Zásadní změny sady Visual Studio 2012
kompilátor
Možnost kompilátoru
/Ylse změnila. Kompilátor ve výchozím nastavení používá tuto možnost, což může vést k LNK2011 chybám za určitých podmínek. Další informace naleznete v tématu /Yl (vložení odkazu PCH pro knihovnu ladění).V kódu, který je zkompilován pomocí
/clr, klíčové slovo 'class' definuje výčet C++11, a nikoli výčet CLR (Common Language Runtime). Pokud chcete definovat výčet CLR, musíte mít explicitní informace o jeho přístupnosti.Pomocí klíčového slova šablona můžete explicitně vyřešit nejednoznačnost závislého názvu (shoda se standardem jazyka C++). V následujícím příkladu je zvýrazněné klíčové slovo šablony povinné k vyřešení nejednoznačnosti. Další informace naleznete v tématu Rozlišení názvů pro závislé typy.
template < typename X = "", typename = "" AY = ""> struct Container { typedef typename AY::template Rebind< X> ::Other AX; };Konstantní výraz typu float již není povolen jako argument šablony, jak je znázorněno v následujícím příkladu.
template<float n=3.14> struct B {}; // error C2993: 'float': illegal type for non-type template parameter 'n'Kód, který je zkompilovaný pomocí možnosti příkazového řádku
/GSa který má chybu mimo rozsah o jednu položku, může vést k ukončení procesu během spouštění, jak je znázorněno v následujícím příkladu pseudokódu.char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminateVýchozí architektura sestavení x86 byla změněna na SSE2; kompilátor proto může generovat instrukce SSE a použije registry XMM k provádění výpočtů s plovoucí desetinou čárkou. Pokud se chcete vrátit k předchozímu chování, použijte příznak kompilátoru
/arch:IA32k určení architektury jako IA32.Kompilátor může vydávat upozornění Upozornění kompilátoru (úroveň 4) C4703 a C4701 v případech, kde dříve nebyla vydávána. Kompilátor používá silnější kontroly použití neinicializovaných místních proměnných typu ukazatele.
Pokud je zadán nový příznak
/HIGHENTROPYVAlinkeru, Systém Windows 8 obvykle způsobí, že přidělení paměti vrátí 64bitovou adresu. (Před Windows 8 taková přidělení obvykle vracela adresy, které byly menší než 2 GB.) Tato změna může odhalit chyby související se zkracováním ukazatelů v existujícím kódu. Ve výchozím nastavení je tento přepínač zapnutý. Chcete-li toto chování zakázat, zadejte/HIGHENTROPYVA:NO.Spravovaný kompilátor (Visual Basic/C#) také podporuje spravované kompilace
/HIGHENTROPYVA. V tomto případě/HIGHENTROPYVAswitchje ale ve výchozím nastavení vypnutý.
integrované vývojové prostředí (IDE)
- Přestože doporučujeme nevytvářet aplikace Windows Forms v C++/CLI, je podporována údržba stávajících aplikací s uživatelským rozhraním C++/CLI. Pokud potřebujete vytvořit aplikaci pro Windows Forms nebo jinou .NET UI aplikaci, použijte C# nebo Visual Basic. Pro účely interoperability používejte pouze C++/CLI.
Knihovna paralelních vzorů a knihovna Concurrency Runtime
Výčet SchedulerTypeUmsThreadDefault je zastaralý. Specifikace UmsThreadDefault vyvolává upozornění na zastaralost a interně mapuje zpět na ThreadScheduler.
Standardní knihovna
Po zásadní změně mezi standardy C++98/03 a C++11, používání explicitních argumentů šablon pro volání
make_pair()—tak jako vmake_pair<int, int>(x, y)—se obvykle nedaří zkompilovat v rámci Visual C++ v prostředí Visual Studio 2012. Řešením je vždy volatmake_pair()bez explicitních argumentů šablony – jako vmake_pair(x, y). Poskytnutí explicitních argumentů šablony popírá účel funkce. Pokud požadujete přesnou kontrolu nad výsledným typem, použijtepairmístomake_pair- jako vpair<short, short>(int1, int2).Další zásadní změna mezi standardy C++98/03 a C++11: Pokud je A implicitně konvertibilní na B a B je implicitně konvertibilní na C, ale A není implicitně konvertibilní na C, C++98/03 a Visual Studio 2010 umožňovaly
pair<A, X>převést (implicitně nebo explicitně) napair<C, X>. (Druhý typ X, tady není zajímavý a není specifický pro první typ v páru.) Kompilátor C++ v sadě Visual Studio 2012 zjistí, že A není implicitně převoditelný na jazyk C, a odebere převod páru z rozlišení přetížení. Tato změna je pro mnoho scénářů pozitivní. Například přetíženífunc(const pair<int, int>&)afunc(const pair<string, string>&), a volánífunc()spair<const char *, const char *>se zkompiluje s touto změnou. Tato změna však přeruší kód, který se spoléhal na agresivní převody párů. Takový kód lze obvykle opravit provedením jedné části převodu explicitně – například předánímmake_pair(static_cast<B>(a), x)funkce, která očekávápair<C, X>.Variadické šablony simulované ve Visual Studio 2010, jako je
make_shared<T>(arg1, arg2, argN), až do limitu 10 argumentů, generováním přetížení a specializací pomocí preprocesorových mechanismů. V sadě Visual Studio 2012 je tento limit omezen na pět argumentů, aby se zlepšila doba kompilace a spotřeba paměti kompilátoru pro většinu uživatelů. Předchozí limit ale můžete nastavit explicitním definováním _VARIADIC_MAX jako 10 na úrovni projektu.C++11 17.6.4.3.1 [macro.names]/2 zakazuje nahrazení klíčových slov makry při zahrnutí hlaviček standardní knihovny C++. Hlavičky teď generují chyby kompilátoru, pokud detekují klíčová slova nahrazená makrem. (Definování _ALLOW_KEYWORD_MACROS umožňuje kompilaci takového kódu, ale důrazně nedoporučujeme toto použití.) Jako výjimka je ve výchozím nastavení povolena forma
newmakra, protože hlavičky se komplexně chrání pomocí#pragma push_macro("new")/#undef new/#pragma pop_macro("new"). Definování _ENFORCE_BAN_OF_MACRO_NEW dělá přesně to, co jeho název napovídá.Pokud chcete implementovat různé optimalizace a kontroly ladění, implementace standardní knihovny C++ záměrně přeruší binární kompatibilitu mezi verzemi sady Visual Studio (2005, 2008, 2010, 2012). Pokud se používá standardní knihovna C++, zakáže kombinování souborů objektů a statických knihoven kompilovaných pomocí různých verzí do jednoho binárního souboru (EXE nebo DLL) a zakáže předávání objektů standardní knihovny jazyka C++ mezi binárními soubory kompilovanými pomocí různých verzí. Kombinace souborů objektů a statických knihoven (pomocí standardní knihovny jazyka C++, která byla zkompilována pomocí sady Visual Studio 2010 s knihovnami, které byly zkompilovány pomocí kompilátoru jazyka C++ v sadě Visual Studio 2012, generuje chyby linkeru o neshodě _MSC_VER, kde _MSC_VER je makro obsahující hlavní verzi kompilátoru (1700 pro Visual C++ v sadě Visual Studio 2012). Tato kontrola nedokáže rozpoznat kombinování knihoven DLL a nedokáže rozpoznat kombinování, které zahrnuje Visual Studio 2008 nebo starší.
Kromě zjišťování neshod _ITERATOR_DEBUG_LEVEL, které byly implementovány v sadě Visual Studio 2010, kompilátor jazyka C++ v sadě Visual Studio 2012 detekuje neshody knihoven runtime. K těmto neshodám dochází, když jsou možnosti kompilátoru
/MT(statická verze),/MTd(statické ladění),/MD(dynamická verze) a/MDd(dynamické ladění) smíšené.operator<(), ,operator>()operator<=()aoperator>=()byly dříve k dispozici prostd::unordered_mapastdext::hash_maprodiny kontejnerů, i když jejich implementace nebyly užitečné. Tyto nestandardní operátory byly ve Visual C++ ve Visual Studio 2012 odebrány. Kromě toho byla implementaceoperator==()aoperator!=()prostd::unordered_maprodinu rozšířena tak, aby pokrývalastdext::hash_maprodinu. (Doporučujeme, abyste se vyhnuli použitístdext::hash_maprodiny v novém kódu.)C++11 22.4.1.4 [locale.codecvt] určuje, že
codecvt::length()acodecvt::do_length()by měly přijímat upravitelné parametrystateT&, ale Visual Studio 2010 používaloconst stateT&. Kompilátor jazyka C++ v sadě Visual Studio 2012 přebírástateT&podle mandátu standardu. Tento rozdíl je významný pro každého, kdo se pokouší přepsat virtuální funkcido_length().
CRT
Halda C Runtime (CRT), která se používá pro operátor new a funkci malloc(), už není vyhrazená. CRT teď používá haldu procesu. To znamená, že halda není zničena při uvolnění knihovny DLL, takže knihovny DLL, které jsou staticky propojené s CRT, musí zajistit, aby paměť přidělená kódem knihovny DLL byla vyčištěna před jejím uvolněním.
Funkce
iscsymf()se používá se zápornými hodnotami.Struktura
threadlocaleinfostructse změnila tak, aby vyhovovala změnám funkcí národního prostředí.Funkce CRT, které mají odpovídající vnitřní funkce, jako
memxxx(),strxxx(), jsou odebrány z intrin.h. Pokud jste intrin.h zahrnuli pouze pro tyto funkce, musíte nyní zahrnout odpovídající hlavičky CRT.
MFC a ATL
Odebrána podpora Fusion (afxcomctl32.h); takže byly odebrány všechny metody, které jsou definovány v
<afxcomctl32.h>. Soubory<afxcomctl32.h>hlaviček a<afxcomctl32.inl>byly odstraněny.Změnil se název
CDockablePane::RemoveFromDefaultPaneDividiernaCDockablePane::RemoveFromDefaultPaneDivider.Změnil se podpis
CFileDialog::SetDefExtpro použití LPCTSTR, a proto jsou tím ovlivněny buildy Unicode.Odebrání zastaralých kategorií trasování ATL
Změna podpisu
CBasePane::MoveWindowtak, aby přijalconst CRect.Změnil se podpis
CMFCEditBrowseCtrl::EnableBrowseButton.Byly odebrány vlastnosti
m_fntTabsam_fntTabsBoldze třídyCMFCBaseTabCtrl.Byl přidán parametr
CMFCRibbonStatusBarPanedo konstruktorů. (Jedná se o výchozí parametr, a proto neporušuje zdrojový kód.)Přidání parametru do konstruktoru
CMFCRibbonCommandsListBox(Jedná se o výchozí parametr, a proto nenarušuje zdroj.)Jsme odebrali rozhraní API
AFXTrackMouse(a související zpracování časovače). Místo toho použijte rozhraní API Win32TrackMouseEvent.Přidání parametru do konstruktoru
CFolderPickerDialog(Jedná se o výchozí parametr, a proto neporušuje zdroj.)CFileStatuszměna velikosti struktury: Členm_attributese změnil z BYTE na DWORD (aby odpovídal hodnotě vrácené zGetFileAttributes).CRichEditCtrlaCRichEditViewv buildech Unicode používejte MSFTEDIT_CLASS (ovládací prvek RichEdit 4.1) místo RICHEDIT_CLASS (ovládací prvek RichEdit 3.0).Odebráno
AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground, protože je ve Windows Vista, Windows 7 a Windows 8 vždy PRAVDA.Odebráno
AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable, protože je vždy TRUE na Windows Vista, Windows 7 a Windows 8.Bylo odebráno
AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea. Volání rozhraní API systému Windows přímo ve Windows Vista, Windows 7 a Windows 8.Odstraněno
AFX_GLOBAL_DATA::DwmDefWindowProc. Volání rozhraní API systému Windows přímo ve Windows Vista, Windows 7 a Windows 8.Přejmenováno
AFX_GLOBAL_DATA::DwmIsCompositionEnablednaIsDwmCompositionEnabled, aby se vyloučila kolize názvů.Změněné identifikátory pro řadu interních časovačů MFC a přesunuté definice do afxres.h (AFX_TIMER_ID_*).
Změnil jsem podpis metody
OnExitSizeMovetak, aby odpovídal makru ON_WM_EXITSIZEMOVE:CFrameWndExCMDIFrameWndExCPaneFrameWnd
Změnil se název a podpis
OnDWMCompositionChangedtak, aby souhlasil s makrem ON_WM_DWMCOMPOSITIONCHANGED:CFrameWndExCMDIFrameWndExCPaneFrameWnd
Změna podpisu
OnMouseLeavemetody tak, aby souhlasila s makrem ON_WM_MOUSELEAVE:CMFCCaptionBarCMFCColorBarCMFCHeaderCtrlCMFCProperySheetListBoxCMFCRibbonBarCMFCRibbonPanelMenuBarCMFCRibbonRichEditCtrlCMFCSpinButtonCtrlCMFCToolBarNahraditTentoTextCMFCToolBarComboBoxEditCMFCToolBarEditCtrlCMFCAutoHideBar
Změna podpisu
OnPowerBroadcasttak, aby odpovídal makru ON_WM_POWERBROADCAST:CFrameWndExCMDIFrameWndEx
Změnil se podpis
OnStyleChanged, aby odpovídal makru ON_WM_STYLECHANGED:CMFCListCtrlCMFCStatusBar
Přejmenování interní metody
FontFamalyProcFontsnaFontFamilyProcFonts.Odebrali jsme mnoho globálních statických
CStringobjektů, abychom v některých situacích odstranili úniky paměti (nahrazeno #definy), a také následující členské proměnné třídy:CKeyBoardManager::m_strDelimiterCMFCPropertyGridProperty::m_strFormatCharCMFCPropertyGridProperty::m_strFormatShortCMFCPropertyGridProperty::m_strFormatLongCMFCPropertyGridProperty::m_strFormatUShortCMFCPropertyGridProperty::m_strFormatULongCMFCPropertyGridProperty::m_strFormatFloatCMFCPropertyGridProperty::m_strFormatDoubleCMFCToolBarImages::m_strPngResTypeCMFCPropertyGridProperty::m_strFormat
Změnil se podpis
CKeyboardManager::ShowAllAcceleratorsa byl odstraněn parametr oddělovače akcelerátoru.Přidána
CPropertyPage::GetParentSheet, a ve tříděCPropertyPagezavolat ji namísto voláníGetParentpro získání správného rodičovského okna listu, které může být nadřazené nebo prarodičovské oknoCPropertyPage. Možná budete muset změnit kód tak, aby volalGetParentSheetmístoGetParent.Opravili jsme nevyvážené #pragma warning(push) v ATLBASE.H, což způsobovalo nesprávné zakázání upozornění. Tato upozornění jsou nyní správně povolená po zpracování ATLBASE.H.
Přesunuté metody související s D2D z AFX_GLOBAL_DATA do _AFX_D2D_STATE:
GetDirectD2dFactoryGetWriteFactoryGetWICFactoryInitD2DReleaseD2DRefsIsD2DInitializedD2D1MakeRotateMatrixMísto toho, abyste například zavolali
afxGlobalData.IsD2DInitialized, zavolejteAfxGetD2DState->IsD2DInitialized.
Byly odstraněny zastaralé soubory ATL*.CPP ze složky \atlmfc\include\.
Inicializace
afxGlobalDataje nyní prováděna na vyžádání namísto v čase inicializace CRT, aby splňovala požadavkyDLLMain.Do třídy
CMFCOutlookBarPanebyla přidána metodaRemoveButtonByIndex.Opraveno
CMFCCmdUsageCount::IsFreqeuntlyUsedCmdnaIsFrequentlyUsedCmd.Opravili jsme několik výskytů
RestoreOriginalstatenaRestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).Odebrané nepoužité metody z
CDockablePane:SetCaptionStyle,IsDrawCaption,IsHideDisabledButtons,GetRecentSiblingPaneInfo, aCanAdjustLayout.Byly odstraněny
CDockablePanestatické členské proměnném_bCaptionTextam_bHideDisabledButtons.Byla přidána metoda přetížení
DeleteStringdoCMFCFontComboBox.Odebrané nepoužívané metody z
CPane:GetMinLengthaIsLastPaneOnLastRow.Přejmenováno
CPane::GetDockSiteRow(CDockingPanesRow *)naCPane::SetDockSiteRow.
Zásadní změny sady Visual Studio 2010
kompilátor
Klíčové
autoslovo má nový výchozí význam. Vzhledem k tomu, že použití starého významu je vzácné, většina aplikací nebude touto změnou ovlivněna.static_assertNové klíčové slovo je zavedeno, což způsobí konflikt názvů, pokud v kódu již existuje identifikátor podle daného názvu.Podpora nového zápisu lambda vylučuje možnost kódování necitovaného identifikátoru GUID v atributu uuid IDL.
Rozhraní .NET Framework 4 zavádí koncept poškozených výjimek stavu, což jsou výjimky, které zanechávají proces ve stavu, který nelze opravit. Ve výchozím nastavení nelze zachytit výjimku poškozeného stavu ani s možností kompilátoru /EHa, která zachytí všechny ostatní výjimky. Pokud chcete explicitně zachytit výjimku poškozeného stavu, použijte příkazy __try-__except. Nebo použijte atribut [HandledProcessCorruptedStateExceptions], který funkci umožní zachytit výjimky poškozeného stavu. Tato změna má vliv především na programátory systému, kteří mohou muset zachytit výjimku poškozeného stavu. Osm výjimek jsou 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. Další informace o těchto výjimkách naleznete v makre GetExceptionCode .
Revidovaná
/GSmožnost kompilátoru chrání před přetečením vyrovnávací paměti komplexněji než v předchozích verzích. Tato verze může vložit další kontroly zabezpečení do softwarového zásobníku, které můžou snížit výkon. Pomocí nového__declspec(safebuffers)klíčového slova instruujte kompilátoru, aby nevkládaly kontroly zabezpečení pro konkrétní funkci.Pokud kompilujete s možnostmi
/GL(Optimalizace celého programu) a/clr(kompilace Common Language Runtime), bude možnost/GLignorována. Tato změna byla provedena, protože kombinace možností kompilátoru poskytovala malou výhodu. Vzhledem k této změně se zlepšil výkon sestavení.Ve výchozím nastavení je podpora trigrafů v sadě Visual Studio 2010 zakázaná. Pomocí možnosti kompilátoru
/Zc:trigraphspovolte podporu trigrafů. Trigraf se skládá ze dvou po sobě jdoucích otazník (??") následovaných jedinečným třetím znakem. Kompilátor nahradí trigraf odpovídajícím interpunkčním znakem. Kompilátor například nahradí??=trigraf znakem #. Ve zdrojových souborech jazyka C použijte trigrafy, pokud používají znakové sady, které neobsahují vhodné grafické reprezentace pro některé interpunkční znaky.Linker už nepodporuje optimalizaci pro Windows 98. Možnost
/OPT(Optimalizace) vytvoří chybu v době kompilace, pokud zadáte/OPT:WIN98nebo/OPT:NOWIN98.Byly změněny výchozí možnosti kompilátoru určené vlastnostmi systému sestavení RuntimeLibrary a DebugInformationFormat. Ve výchozím nastavení jsou tyto vlastnosti sestavení zadány v projektech vytvořených verzí visual C++ 7.0 až 10.0. Pokud migrujete projekt vytvořený visual C++ 6.0, zvažte, zda chcete zadat hodnotu pro tyto vlastnosti.
V aplikaci Visual Studio 2010, RuntimeLibrary = MultiThreaded (
/MD) a DebugInformationFormat = ProgramDatabase (/Zi). Ve Visual C++ 9.0, RuntimeLibrary = MultiThreaded (/MT) a DebugInformationFormat = Disabled.
CLR
- Kompilátory Microsoft C# a Visual Basic nyní mohou vytvářet sestavení bez primární interoperační sestavy (no-PIA). Sestavení bez PIA může používat COM typy i bez nasazení příslušného primárního sestavení pro spolupráci (PIA). Při využívání sestavení bez PIA vytvořených pomocí jazyka Visual C# nebo Visual Basic je nutné na příkazovém řádku kompilace nejprve odkázat na sestavení PIA, a teprve potom na jakékoli sestavení no-PIA, které používá danou knihovnu.
Projekty jazyka C++ sady Visual Studio a MSBuild
Projekty visual Studio C++ jsou teď založené na nástroji MSBuild. Soubory projektu proto používají nový formát souboru XML a příponu souboru .vcxproj. Visual Studio 2010 automaticky převede soubory projektu ze starších verzí sady Visual Studio do nového formátu souborů. Existující projekt je ovlivněn, pokud závisí na předchozím nástroji sestavení, VCBUILD.exe, nebo příponě souboru projektu .vcproj.
V dřívějších verzích podporuje Visual C++ pozdní vyhodnocení seznamů vlastností. Například nadřazený seznam vlastností může importovat podřízený seznam vlastností a nadřazený může použít proměnnou definovanou v podřízeném k definování dalších proměnných. Pozdní vyhodnocení dovolilo rodiči používat dětskou proměnnou i před importem vlastnostního listu dítěte. V sadě Visual Studio 2010 nelze proměnnou listu projektu použít dříve, než je definována, protože nástroj MSBuild podporuje pouze předčasné vyhodnocení.
integrované vývojové prostředí (IDE)
Dialogové okno ukončení aplikace už aplikaci neskoncuje. V předchozích verzích se při
abort()terminate()zavření maloobchodního sestavení aplikace v knihovně C Run-Time zobrazila zpráva ukončení aplikace v okně konzoly nebo dialogovém okně. Zpráva částečně řekla: "Tato aplikace požádala Runtime, aby jej ukončil neobvyklým způsobem. Další informace vám poskytne tým podpory aplikace. Zpráva o ukončení aplikace byla redundantní, protože systém Windows následně zobrazil aktuální obslužnou rutinu ukončení, což byla obvykle dialogové okno Zasílání zpráv o chybách systému Windows (Dr. Watson) nebo ladicí program sady Visual Studio. Počínaje sadou Visual Studio 2010 se zpráva nezobrazuje v knihovně runtime jazyka C. Modul runtime navíc brání ukončení aplikace před spuštěním ladicího programu. Jedná se o zásadní změnu pouze v případě, že závisíte na předchozím chování zprávy o ukončení aplikace.Technologie IntelliSense konkrétně pro Visual Studio 2010 nefunguje pro kód nebo atributy C++/CLI, funkce Najít všechny odkazy nefunguje pro místní proměnné a model kódu nenačítá názvy typů z importovaných sestavení nebo překládá typy na plně kvalifikované názvy.
Knihovny
Třída SafeInt je součástí jazyka Visual C++ a již není součástí samostatného stahování. Jedná se o zásadní změnu pouze v případě, že jste vyvinuli třídu, kterou jste pojmenovali "SafeInt".
Model nasazení knihoven už nepoužívá manifesty k vyhledání konkrétní verze dynamické knihovny odkazů. Místo toho název každé dynamické knihovny odkazů obsahuje její číslo verze a tento název použijete k vyhledání knihovny.
V předchozích verzích sady Visual Studio jste mohli znovu sestavit knihovny runtime. Visual Studio 2010 už nepodporuje vytváření vlastních kopií souborů knihovny runtime jazyka C.
Standardní knihovna
Hlavička
<iterator>už není zahrnuta automaticky mnoha dalšími soubory hlaviček. Místo toho tuto hlavičku explicitně zahrňte, pokud potřebujete podporu samostatných iterátorů definovaných v hlavičce. Existující projekt je ovlivněn, pokud závisí na předchozím nástroji sestavení, VCBUILD.exe, nebo příponě souboru projektu .vcproj.iterator.V záhlaví
<algorithm>jsou odstraněny funkcechecked_*aunchecked_*. A v<iterator>> záhlaví bylachecked_iteratortřída odstraněna aunchecked_array_iteratortřída byla přidána.Konstruktor
CComPtr::CComPtr(int)je odebrán. Tento konstruktor umožnil vytvoření objektuCComPtrz makra NULL, ale byl nepotřebný a umožňoval nesmyslné konstrukce z nenulových celých čísel.Hodnota A
CComPtrje stále možné vytvořit z hodnoty NULL, která je definována jako 0, ale pokud se vytvoří z jiného čísla než literál 0, selže. Místo toho použijtenullptr.Byly odebrány následující
ctypečlenské funkce:ctype::_Do_narrow_s,ctype::_Do_widen_s,ctype::_narrow_s,ctype::_widen_s. Pokud aplikace používá některou z těchto členských funkcí, musíte ji nahradit odpovídající nezabezpečenou verzí:ctype::do_narrow,ctype::do_widen,ctype::narrow.ctype::widen
Knihovny CRT, MFC a ATL
Uživatelům byla odebrána podpora pro vytváření knihoven CRT, MFC a ATL. Například není k dispozici žádný vhodný soubor NMAKE. Uživatelé ale stále mají přístup ke zdrojovému kódu těchto knihoven. A dokument, který popisuje možnosti nástroje MSBuild, které Microsoft používá k sestavení těchto knihoven, bude pravděpodobně publikován v blogu týmu Visual C++.
Podpora MFC pro IA64 byla odebrána. Podpora CRT a ATL v IA64 je však stále k dispozici.
Ordnály se již znovu nepoužívají v souborech definice modulu MFC (.def). Tato změna znamená, že se ordinaly nebudou lišit mezi minor verzemi a binární kompatibilita pro aktualizace Service Pack a implementace rychlých oprav bude vylepšena.
Do
CDocTemplatetřídy byla přidána nová virtuální funkce. Tato nová virtuální funkce je CDocTemplate třída. Předchozí verzeOpenDocumentFileměla dva parametry. Nová verze má tři parametry. Pro podporu správce restartování musí každá třída odvozená zCDocTemplateimplementovat verzi, která má tři parametry. Nový parametr jebAddToMRU.
Makra a proměnné prostředí
- Proměnná prostředí __MSVCRT_HEAP_SELECT se už nepodporuje. Proměnná prostředí byla odstraněna a není za ni žádná náhrada.
Microsoft Macro Assembler – referenční dokumentace
- Z referenčního kompilátoru Microsoft Macro Assembler bylo odebráno několik direktiv. Odebrané direktivy jsou
.186,.286,.286P,.287,.8086,.8087a.NO87.
Zásadní změny sady Visual Studio 2008
kompilátor
Platformy Windows 95, Windows 98, Windows ME a systém Windows NT se už nepodporují. Tyto operační systémy byly odebrány ze seznamu cílových platforem.
Kompilátor již nepodporuje více atributů, které byly přímo přidružené k ATL Serveru. Následující atributy se už nepodporují:
perf_counter
perf_objekt
perfmon
zpracovatel požadavků
zpracovatel SOAP
SOAP záhlaví
soap_method (metoda SOAP)
název_štítku
Projekty Visual Studio C++
Při upgradu projektů z předchozích verzí sady Visual Studio možná budete muset upravit makra WINVER a _WIN32_WINNT tak, aby byla větší nebo rovna 0x0500.
Počínaje sadou Visual Studio 2008 nemá průvodce novým projektem možnost vytvořit projekt SQL Serveru C++. Projekty SQL Serveru vytvořené pomocí starší verze sady Visual Studio budou stále kompilovat a fungovat správně.
Soubor hlaviček rozhraní WINDOWS API Winable.h byl odebrán. Místo toho zahrňte Winuser.h.
Knihovna rozhraní Windows API Rpcndr.lib byla odebrána. Odkazujte místo toho pomocí rpcrt4.lib.
CRT
Byla odebrána podpora pro Windows 95, Windows 98, Windows Millennium Edition a systém Windows NT 4.0.
Byly odebrány následující globální proměnné:
_osplatform
_osver
_winmajor
_winminor
_winver
Následující funkce byly odebrány. Použijte funkce
GetVersionrozhraní WINDOWS API neboGetVersionExmísto toho:_get_osplatform
_get_osver
_get_winmajor
_get_winminor
_get_winver
Syntaxe poznámek SAL se změnila. Další informace najdete v tématu Poznámky SAL.
Filtr IEEE teď podporuje instrukční sadu SSE 4.1. Další informace najdete v tématu
_fpieee_flt.Knihovny runtime jazyka C, které jsou dodávány se sadou Visual Studio, již nejsou závislé na systémové knihovně DLL msvcrt.dll.
Standardní knihovna
Byla odebrána podpora pro Windows 95, Windows 98, Windows Millennium Edition a systém Windows NT 4.0.
Při kompilaci v režimu ladění s definovaným _HAS_ITERATOR_DEBUGGING (nahrazeno _ITERATOR_DEBUG_LEVEL po sadě Visual Studio 2010) aplikace nyní vyvolá výjimku, když se iterátor pokusí inkrementovat nebo dekrementovat přes hranice podkladového kontejneru.
Členová proměnná c třídy Stack je nyní deklarována chráněná. Dříve byla tato členová proměnná deklarována jako veřejná.
Chování
money_get::do_getse změnilo. Dříve, při analýze peněžní částky s více desetinnými místy, než požadujefrac_digits,do_getje všechny spotřebovávala.do_getTeď po použití většinyfrac_digitsznaků přestane parsovat.
knihovna ATL
AtL nejde sestavit bez závislosti na CRT. V dřívějších verzích sady Visual Studio můžete pomocí #define ATL_MIN_CRT vytvořit projekt ATL minimálně závislý na CRT. V sadě Visual Studio 2008 jsou všechny projekty ATL minimálně závislé na CRT bez ohledu na to, jestli je definován ATL_MIN_CRT.
Základ kódu ATL Serveru byl vydán jako sdílený zdrojový projekt v CodePlexu a není nainstalován jako součást sady Visual Studio. Třídy pro kódování a dekódování dat z atlenc.h a užitkové funkce a třídy z atlutil.h a atlpath.h byly zachovány a jsou nyní součástí knihovny ATL. Několik souborů přidružených k ATL Serveru již není součástí sady Visual Studio.
Některé funkce už nejsou součástí knihovny DLL. Jsou stále umístěné v importní knihovně. To neovlivní kód, který staticky používá funkce. Ovlivní pouze kód, který tyto funkce používá dynamicky.
Makra PROP_ENTRY a PROP_ENTRY_EX jsou zastaralá a nahrazena makry PROP_ENTRY_TYPE a PROP_ENTRY_TYPE_EX z bezpečnostních důvodů.
Sdílené třídy ATL/MFC
AtL nejde sestavit bez závislosti na CRT. V dřívějších verzích sady Visual Studio jste mohli použít
#define ATL_MIN_CRT, aby projekt ATL byl minimálně závislý na CRT. V sadě Visual Studio 2008 jsou všechny projekty ATL minimálně závislé na CRT bez ohledu na to, jestli je definován ATL_MIN_CRT.Základ kódu ATL Serveru byl vydán jako sdílený zdrojový projekt v CodePlexu a není nainstalován jako součást sady Visual Studio. Třídy pro kódování a dekódování dat z atlenc.h a užitkové funkce a třídy z atlutil.h a atlpath.h byly zachovány a jsou nyní součástí knihovny ATL. Několik souborů přidružených k ATL Serveru již není součástí sady Visual Studio.
Některé funkce už nejsou součástí knihovny DLL. Jsou stále umístěné v importní knihovně. To neovlivní kód, který staticky používá funkce. Ovlivní pouze kód, který tyto funkce používá dynamicky.
knihovna MFC
CTimeTřída: TřídaCTimenyní přijímá kalendářní data od 1. 1. 1900 C.E. namísto 1.1.1970 C.E.Pořadí ovládacích prvků v dialogových oknech MFC: Správné pořadí více prvků v dialogovém okně MFC je narušeno, pokud je do pořadí vložen ActiveX ovládací prvek MFC. Tato změna tento problém opraví.
Můžete například vytvořit aplikaci dialogového okna MFC, která má ovládací prvek ActiveX a několik ovládacích prvků pro úpravy. Umístěte ovládací prvek ActiveX doprostřed pořadí ovládacích prvků pro úpravy. Spusťte aplikaci, klikněte na ovládací prvek pro úpravy, jehož pořadí ovládacích prvků je za ovládacím prvku ActiveX, a potom na kartu. Před touto změnou se fokus dostal na ovládací prvek pro úpravy, který následuje za ovládacím prvku ActiveX, a ne na další ovládací prvek pro úpravy v pořadí ovládacích prvků.
CFileDialogTřída: Vlastní šablony proCFileDialogtřídu nelze automaticky přenést do systému Windows Vista. Jsou stále použitelné, ale nebudou mít další funkce nebo vzhled dialogových oken windows Vista.CWndTřída aCFrameWndtřída: MetodaCWnd::GetMenuBarInfobyla odebrána.Tato
CFrameWnd::GetMenuBarInfometoda je nyní ne virtuální metodou. Další informace naleznete v tématu funkce GetMenuBarInfo v sadě Windows SDK.Podpora ROZHRANÍ MFC ISAPI: MFC už nepodporuje vytváření aplikací pomocí rozhraní ISAPI (Internet Server Application Programming Interface). Pokud chcete vytvořit aplikaci ISAPI, použijte rozšíření ISAPI přímo.
Zastaralá rozhraní API ANSI: Verze ANSI několika metod MFC jsou zastaralé. V budoucích aplikacích používejte verze unicode těchto metod. Další informace naleznete v tématu Požadavky na sestavení pro Windows Vista Běžné ovládací prvky.
Zásadní změny sady Visual Studio 2005
CRT
Řada funkcí je zastaralá. Viz zastaralé funkce CRT.
Mnoho funkcí teď ověřuje jejich parametry a zastaví provádění, pokud jsou zadané neplatné parametry. Toto ověření může přerušit kód, který předává neplatné parametry, a spoléhá na to, že je funkce ignoruje nebo pouze vrací kód chyby. Viz ověření parametru.
Hodnota popisovače souboru -2 se teď používá k označení, že
stdoutastderrnejsou dostupné pro výstup, například v aplikaci pro Windows, která nemá okno konzoly. Použitá předchozí hodnota byla -1. Další informace najdete v tématu _fileno.Knihovny CRT pro jedno vlákno (libc.lib a libcd.lib) byly odebrány. Použijte vícevláknové knihovny CRT. Příznak kompilátoru
/MLse už nepodporuje. V případech, kdy je rozdíl mezi vícevláknovým kódem a kódem s jedním vláknem potenciálně významný, byly přidány neblokované verze některých funkcí.Přetížení pow, double pow(int, int), bylo odstraněno, aby lépe odpovídalo standardu.
Specifikátor formátu %n už není ve výchozím nastavení podporován v žádné skupině funkcí printf, protože je ze své podstaty nezabezpečený. Pokud je zjištěna hodnota %n, výchozím chováním je vyvolání neplatné obslužné rutiny parametru. Pro povolení %n podpory použijte
_set_printf_count_output(viz také_get_printf_count_output).sprintfNyní vytiskne záporné znaménko u nuly s nulovým znaménkem.swprintfbyla změněna tak, aby odpovídala standardu; teď vyžaduje parametr velikosti. Formulář bez parametruswprintfvelikosti je zastaralý._set_security_error_handlerbylo odebráno. Odeberte všechna volání této funkce; Výchozí obslužná rutina je mnohem bezpečnější způsob řešení chyb zabezpečení.time_tje teď 64bitová hodnota (pokud není definována _USE_32BIT_TIME_T).Funkce
_spawn,_wspawnnyní ponechajíerrnonedotčený při úspěchu, jak je specifikováno standardem C.RtC teď ve výchozím nastavení používá široké znaky.
Funkce podpory řídicího slova pro operace s plovoucí desetinnou čárkou jsou doporučeny nepoužívat pro aplikace zkompilované pomocí
/CLRnebo/CLR:PURE. Ovlivněné funkce jsou_clear87,_clearfp._control87_controlfp_fpreset_status87_statusfpUpozornění na vyřazení můžete zakázat definováním _CRT_MANAGED_FP_NO_DEPRECATE, ale použití těchto funkcí ve spravovaném kódu je nepředvídatelné a nepodporované.Některé funkce teď vrací ukazatele const. Staré, ne-konstantní chování lze obnovit definováním _CONST_RETURN. Ovlivněné funkce jsou
memchr, wmemchr
strchr, wcschr, _mbschr, _mbschr_l
strpbrk, wcspbrk, _mbspbrk, _mbspbrk_l
strrchr, wcsrchr, _mbsrchr, _mbsrchr_l
strstr, wcsstr, _mbsstr, _mbsstr_l
Při propojení s Setargv.obj nebo Wsetargv.obj už není možné potlačit rozšíření zástupného znaku na příkazovém řádku uzavřením do dvojitých uvozovek. Další informace naleznete v tématu Expanze zástupných znaků v argumentech.
Standardní knihovna (2005)
Třída výjimky (umístěná v
<exception>hlavičce) byla přesunuta dostdoboru názvů. V předchozích verzích byla tato třída v globálním oboru názvů. Pokud chcete vyřešit případné chyby, které značí, že třídu výjimek nelze najít, přidejte do kódu následující příkaz using:using namespace std;Při volání
valarray::resize()dojde ke ztrátě obsahuvalarraya nahradí se výchozími hodnotami. Metodaresize()je určena k opětovnému inicializovánívalarrayspíše než k jeho dynamickému růstu jako u vektorů.Ladicí iterátory: Aplikace vytvořené pomocí ladicí verze knihovny C-Runtime, které používají iterátory nesprávně, mohou začít zobrazovat aserty za běhu. Chcete-li tyto aserce zakázat, je potřeba definovat _HAS_ITERATOR_DEBUGGING (nahrazeno
_ITERATOR_DEBUG_LEVELpočínaje Visual Studiem 2010) na 0. Více informací naleznete v tématu Podpora ladicího iterátoru.
Zásadní změny visual C++ .NET 2003
kompilátor
Uzavírací závorky se teď vyžadují pro definovanou direktivu preprocesoru (C2004).
Explicitní specializace už nenaleznou parametry šablony z primární šablony (Chyba kompilátoru C2146).
Chráněný člen (n) je přístupný pouze prostřednictvím členské funkce třídy (B), která dědí z třídy (A), z níž (n) je členem (Chyba kompilátoru C2247).
Vylepšené kontroly přístupnosti v kompilátoru teď detekují nepřístupné základní třídy (chyba kompilátoru C2248).
Výjimku nelze zachytit, pokud je destruktor a/nebo konstruktor kopírování nepřístupný (C2316).
Výchozí argumenty u ukazatelů na funkce už nejsou povolené (Chyba kompilátoru C2383).
Statický datový člen nelze inicializovat prostřednictvím odvozené třídy (Chyba kompilátoru C2477).
Inicializace
typedefstandardu není povolená a teď generuje chybu kompilátoru (Chyba kompilátoru C2513).boolje teď správný typ (chyba kompilátoru C2632).UDC teď může vytvořit nejednoznačnost s přetíženými operátory (C2666).
Další výrazy jsou nyní považovány za platné konstanty ukazatele null (Chyba kompilátoru C2668).
Šablona<> je teď vyžadována na místech, kde by kompilátor dříve předpokládal (chyba kompilátoru C2768).
Explicitní specializace členské funkce mimo třídu není platná, pokud už je funkce explicitně specializovaná prostřednictvím specializace podle třídy šablony (Chyba kompilátoru C2910).
Parametry šablony netypového parametru čísla s plovoucí desetinnou čárkou již nejsou povoleny (Chyba kompilátoru C2993).
Šablony tříd nejsou povolené jako argumenty typu šablony (C3206).
Názvy přátelských funkcí již nejsou vkládány do obsahujícího oboru názvů (Chyba kompilátoru C3767).
Kompilátor už nebude přijímat nadbytečné čárky v makru (C4002).
Objekt typu POD vytvořený inicializátorem formuláře () bude ve výchozím nastavení inicializován (C4345).
Název typename se teď vyžaduje, pokud se závislý název považuje za typ (upozornění kompilátoru (úroveň 1) C4346).
Funkce, které byly nesprávně považovány za specializace šablon, se už nepovažují za (C4347).
Statické datové členy nelze inicializovat prostřednictvím odvozené třídy (C4356).
Specializaci šablony třídy je potřeba definovat před jejím použitím v návratovém typu (upozornění kompilátoru (úroveň 3) C4686).
Kompilátor teď hlásí nedostupný kód (C4702).