Historie změn v Microsoft C/C++ 2003 – 2015
tento článek popisuje všechny zásadní změny z Visual Studio 2015 se vrátí do Visual Studio 2003 a v tomto článku jsou uvedené "nové chování" nebo "teď" odkazují na Visual Studio 2015 a novější. pojem "staré chování" a "před" odkazují na Visual Studio 2013 a starší verze.
informace o nejnovější verzi Visual Studio najdete v tématu co je nového v jazyce C++ v tématu Visual Studio a vylepšení shody c++ v Visual Studio.
Poznámka
neexistují žádné binární změny mezi Visual Studio 2015 a Visual Studio 2017.
pokud upgradujete na novou verzi Visual Studio, může dojít k chybám kompilace a/nebo za běhu v kódu, který byl dříve zkompilován a spuštěn správně. Změny v nové verzi, které způsobují takové problémy, se označují jako zásadní změnya obvykle jsou vyžadovány změnami ve standardu jazyka C++, signaturami funkcí nebo rozložením objektů v paměti.
Aby nedocházelo k chybám za běhu, které je obtížné rozpoznat a diagnostikovat, doporučujeme, abyste nikdy nepoužili staticky odkaz na binární soubory kompilovány pomocí jiné verze kompilátoru. Když upgradujete projekt EXE nebo DLL, nezapomeňte také provést upgrade knihoven, na které odkazuje. Neprovádějte typy CRT (C Runtime) nebo standardní knihovna C++ (standardní knihovna C++) mezi binárními soubory, včetně knihoven DLL, kompilovány pomocí různých verzí kompilátoru. Další informace najdete v tématu možné chyby při předávání objektů CRT napříč hranicemi knihoven DLL.
Nikdy byste neměli psát 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 najdete v tématu přenositelnost na hranicích ABI.
Navíc průběžná vylepšení shody kompilátoru mohou někdy změnit způsob, jakým kompilátor rozumí vašemu existujícímu zdrojovému kódu. Například můžete najít nové nebo jiné chyby během sestavení nebo dokonce i rozdíly v kódu, které dříve vytvořili a zdály se pracovat správně. I když tato vylepšení nejsou zásadními změnami, jako jsou popsané v tomto dokumentu, možná budete muset provést změny ve zdrojovém kódu pro vyřešení těchto problémů:
změny shody Visual Studio 2015
Běhová knihovna jazyka C (CRT)
Obecné změny
Refaktorované binární soubory
Knihovna CRT byla refaktorovaná do dvou různých binárních souborů: Universal CRT (ucrtbase), který obsahuje většinu standardních funkcí a knihovnu runtime VC (vcruntime). Knihovna vcruntime obsahuje funkce související s kompilátorem, jako je zpracování výjimek, a vnitřní objekty. Pokud používáte výchozí nastavení projektu, pak tato změna nemá vliv na to, že linker bude automaticky používat nové výchozí knihovny. Pokud jste nastavili vlastnost linkeru projektu Ignorovat všechny výchozí knihovny na hodnotu Ano nebo používáte možnost linkeru na příkazovém řádku, musíte aktualizovat seznam knihoven (ve vlastnosti Další závislosti ) tak, aby zahrnovaly nové, refaktoringované knihovny. Nahraďte starou knihovnu CRT (Libcmt. lib, LIBCMTD. lib, Msvcrt. lib, msvcrtd. lib) ekvivalentními refaktoring knihovny. Pro každou ze dvou předaných knihoven jsou k dispozici statické (. lib) a dynamické (.dll) verze a verze (bez přípony) a ladicí verze (s příponou "d"). Dynamické verze obsahují knihovnu importu, se kterou propojíte. Dvě refaktorované knihovny jsou Universal CRT, konkrétně ucrtbase.dll nebo ucrtbase. lib, ucrtbased.dll nebo ucrtbased. lib a knihovna runtime VC, libvcruntime. lib, vcruntimeverze.dll, libvcruntimed. lib a vcruntimedverze.dll. verze v Visual Studio 2015 i Visual Studio 2017 je 140. Viz funkce knihovny CRT.
<locale. h>
localeconv
Funkce localeconv deklarovaná v locale. h teď funguje správně i v případě, že je povoleno národní prostředí pro vlákno . V předchozích verzích knihovny Tato funkce vrátila
lconvdata globálního národního prostředí, nikoli národním prostředí vlákna.Použijete-li místní prostředí pro vlákno, měli byste kontrolovat použití nástroje
localeconv. Pokud váš kód předpokládá, želconvvracená data jsou pro globální národní prostředí, měli byste je opravit.
<Math. h>
Přetížení C++ funkcí matematické knihovny
V předchozích verzích < Math. h > definovala některé, ale ne všechny, z přetížení jazyka C++ pro funkce matematické knihovny. Zbytek přetížení byl v <> hlavičce cmath. Kód, který obsahuje pouze < Math. h, > může mít problémy s řešením přetížení funkce. V současné době byly přetěžování jazyka C++ odstraněny ze < matematického. h > a jsou nalezeny pouze v < cmath > .
Chcete-li vyřešit chyby, zahrňte < cmath > a získejte deklarace funkcí, které byly odebrány z < matematického. 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í desetinnou čárkou,,,,,acosacoshasinasinhatanatanh,atan2,cbrt,ceil,copysign,cos,cosh,erf,erfcexpexp2expm1fabsfdimfloorfmafmaxfminfmodfrexphypotilogbldexplgammallrintllroundloglog10log1plog2lrintlroundmodfnearbyintnextafternexttowardremainderremquorintroundscalblnscalbnsinsinhsqrttantanhtgamma,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, atrunc
Pokud máte kód, který používá
abss typem s plovoucí desetinnou čárkou, který obsahuje pouze < hlavičku Math. h > , verze s plovoucí desetinnou čárkou již nebudou k dispozici. Volání nyní překládá naabs(int), a to i s argumentem s plovoucí desetinnou čárkou, která vytváří chybu:warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of dataOprava tohoto upozornění je nahradit volání
abss verzí s plovoucí desetinnou čárkouabs, napříkladfabspro dvojitý argument nebofabsfargumentem typu float, nebo zahrnout <> hlavičku cmath a pokračovat v používáníabs.Shoda s plovoucí desetinnou čárkou
Bylo provedeno mnoho změn v knihovně Math pro zlepšení dodržování specifikace IEEE-754 a přílohy F specifikací C11 s ohledem na vstupy zvláštních případů, jako je hodnoty NaN a nekonečno. Například tiché vstupy NaN, které byly často zpracovány jako 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 při kompilaci, ale mohou způsobit, že se programy chovají jinak a správně podle standardu.
FLT_ROUNDS
v Visual Studio 2013 se makro FLT_ROUNDS rozšířilo na konstantní výraz, který byl nesprávný, protože režim zaokrouhlení lze konfigurovat za běhu, například voláním fesetround. Makro FLT_ROUNDS je teď dynamické a správně odráží aktuální režim zaokrouhlení.
<nové > a < nové. h>
nové a odstranit
V předchozích verzích knihovny byly vyexportovány funkce operátora New a DELETE definované implementací z běhové knihovny DLL (například msvcr120.dll). Tyto funkce operátora jsou nyní vždy staticky propojeny do vašich binárních souborů i při použití knihoven DLL knihoven modulu runtime.
Nejedná se o zásadní změnu pro nativní nebo smíšený kód (
/clr), ale pro kód kompilovaný jako/clrmůže tato změna způsobit selhání kompilace kódu. Pokud kompilujete kód jako/clr:pure, může být nutné přidat#include <new>nebo vyřešit#include <new.h>chyby sestavení z důvodu této změny./clr:puremožnost je zastaralá v Visual Studio 2015 a nepodporovaná v Visual Studio 2017. Kód, který musí být "Pure", by měl být portem C#.
<Process. h>
_beginthread a _beginthreadex
Funkce _beginthread a _beginthreadex nyní obsahují odkaz na modul, ve kterém je procedura vlákna definována pro dobu trvání vlákna. To pomáhá zajistit, že moduly nebudou uvolněny, dokud vlákno nebude dokončeno.
<STDARG. h>
va_start a odkazové typy
Při kompilování kódu jazyka C++ va_start nyní ověřuje v době kompilace, že argument předaný do něj není odkazový typ. Argumenty typu odkazu jsou zakázané standardem C++.
<stdio. h > a < CONIO. h>
Rodina funkcí printf a scanf je teď definovaná jako inline.
Definice všech
printffunkcí a bylyscanfpřesunuty do < stdio. h > , < CONIO. h > a dalších hlaviček CRT. Tato zásadní změna vede k chybě linkeru (LINKERŮ LNK2019, nerozpoznaný externí symbol) pro všechny programy, které tyto funkce deklarovaly místně 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 (tedy přidat#include <stdio.h>) a vložené funkce, ale pokud nechcete změnit kód pro zahrnutí těchto hlavičkových souborů, alternativním řešením je přidat další knihovnu do vstupu linkeru, legacy_stdio_definitions. lib.chcete-li přidat tuto knihovnu do vstupu linkeru v integrovaném vývojovém prostředí, otevřete kontextovou nabídku uzlu projektu, zvolte možnost vlastnosti, poté v dialogovém okně vlastnosti Project zvolte možnost linkera upravte vstup linkeru tak, aby se přidal do seznamu odděleného středníkem.
pokud projekt odkazuje na statické knihovny, které byly zkompilovány s vydáním Visual Studio starším než 2015, linker může hlásit nevyřešený externí symbol. Tyto chyby můžou odkazovat na interní definice pro
_iob,_iob_funcnebo související importy pro určité < funkce stdio. h > ve formě_iob*. 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 knihovnou třetí strany, pro kterou není k dispozici zdroj, 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, která kompilujete se starší verzí kompilátoru a knihoven.Upozornění
pokud propojujete s Windows SDK 8,1 nebo starším, můžete se setkat s těmito nevyřešenými chybami externích symbolů. V takovém případě byste tuto chybu měli vyřešit přidáním legacy_stdio_definitions. lib do vstupu linkeru, jak je popsáno výše.
Pro řešení chyb nevyřešených symbolů můžete zkusit použít dumpbin.exe k prohlédnutí symbolů definovaných v binárním souboru. Zkuste zobrazit symboly definované v knihovně pomocí následujícího příkazového řádku.
dumpbin.exe /LINKERMEMBER somelibrary.libZíská a _getws
Funkce Get a _getws byly odebrány. Funkce Get byla ze standardní knihovny jazyka C v C11 odebrána, protože ji nelze bezpečně použít. _Getws funkce byla rozšíření společnosti Microsoft, které bylo ekvivalentní k získání, ale pro velké řetězce. Jako alternativu k těmto funkcím zvažte použití funkcí fgets,fgetws,gets_sa _getws_s.
_cgets a _cgetws
Funkce _cgetsa _cgetws byly odebrány. Jako alternativu k těmto funkcím zvažte použití _cgets_sa _cgetws_s.
Formátování nekonečna a naN
V předchozích verzích by definice a nan měly být formátovány pomocí sady MSVC řetězců sentinelu specifických pro jednotlivé uživatele.
Nekonečno: 1,#INF
Tiché naN: 1,#QNAN
Signaling NaN (Signál naN): 1.#SNAN
Neurčné naN: 1.#IND
Jakýkoli z těchto formátů může mít předponu a může být formátovaný trochu jinak v závislosti na šířce pole a přesnosti (někdy s neobvyklými účinky by například vytiskl
printf("%.2f\n", INFINITY)1,#J, protože #INF by se "zaokrouhloval" na dvoucifernou přesnost). C99 představil nové požadavky na formátování nedefin a nan. Implementace MSVC teď vyhovuje těmto požadavkům. Nové řetězce jsou následující:Nekonečno: inf
Tiché naN: nan
Signalizační naN: nan(snan)
Neurčené naN: nan(ind)
Ke kterékoli z těchto hodnot může mít předponu znaménko. Pokud použijete specifikátor velikosti písmen (%F místo %f), pak se řetězce vytiskou velkými písmeny ( místo ), jak
INFinfje potřeba.Funkce scanf byly upraveny tak, aby parsovány tyto nové řetězce, takže tyto řetězce teď procházou a
scanf.Formátování a analýza s plovoucí desetinnou čárkou
Byly zavedeny nové algoritmy pro formátování a parsování s plovoucí desetinnou čárkou, které zlepšují správnost. Tato změna má vliv na rodiny funkcí printf a scanf a také funkce, jako je strtod.
Staré formátovací algoritmy by generují pouze omezený počet číslic a pak by zbývající desetinná místa vyplnily nulou. Obvykle by mohly generovat řetězce, které by se vrátily zpět na původní hodnotu s plovoucí desetinnou čárkou, ale nebyly skvělé, pokud byste chtěli přesnou hodnotu (nebo jejich nejbližší desetinnou hodnotu). Nové formátovací algoritmy generují tolik číslic, kolik je potřeba k reprezentaci hodnoty (nebo k vyplnění zadané přesnosti). Jako příklad vylepšení; Při tisku velkého množství dvou vezměte v úvahu výsledky:
printf("%.0f\n", pow(2.0, 80))Starý výstup:
1208925819614629200000000Nový výstup:
1208925819614629174706176Staré algoritmy analýzy by zvážení pouze 17 platných číslic ze vstupního řetězce zahodily zbývající číslice. Tento přístup je dostačující k vygenerování úzké aproximace hodnoty reprezentované řetězcem a výsledek je obvykle velmi blízko správně zaokrouhlené výsledku. Nová implementace zohlední všechny stávající číslice a vytvoří správně zaokrouhlený výsledek pro všechny vstupy (až 768 číslic). Kromě toho tyto funkce nyní respektují režim zaokrouhlení (lze ovládat prostřednictvím fesetroundu). To je potenciálně změna chování při rozbíjení, protože tyto funkce můžou vést k různým výsledkům. Nové výsledky jsou vždy správnější než staré výsledky.
Hexadecimální a nekonečno / Analýza NaN s plovoucí desetinnou čárkou
Algoritmy analýzy s plovoucí desetinnou čárkou teď 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 hodnoty NaN, které jsou generovány funkcemi, jak je popsáno
printfvýše.%A a %a nulové odsazení
Specifikátory formátu %a a %A formátuje číslo s plovoucí desetinnou čárkou jako šestnáctkový manissa a binární exponent. V předchozích verzích by
printffunkce nesprávně vynulované řetězce. Například byprintf("%07.0a\n", 1.0)se vytiskl 00x1p+0, kde by měl vytisknut 0x01p+0. Tato chyba byla opravena.%A a %a přesnost
Výchozí přesnost specifikátoru formátu %A a %a byla v předchozích verzích knihovny 6. Výchozí přesnost je teď 13, aby odpovídala standardu C.
Jedná se o změnu chování modulu runtime 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 teď "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
Teď je podporovaný specifikátor formátu/převodu %F. Je funkčně ekvivalentní specifikátoru formátu %f s tím rozdílem, že hodnoty infinities a NaN jsou formátovány velkými písmeny.
V předchozích verzích se implementace používala k analýze F a N jako modifikátorů délky. Toto chování bylo datováno zpět k stáří segmentovaných adresní prostorů: tyto modifikátory délky byly použity k označení dalekosedlových a nejbližších ukazatelů, jako například %Fp nebo %Ns. Toto chování bylo odebráno. Pokud se zjistí %F, bude se považovat za specifikátor formátu %F. Pokud se zjistí %N, bude se považovat za neplatný parametr.
Exponentní formátování
Specifikátory formátu %e a %E formátuje číslo s plovoucí desetinnou čárkou jako desetinnou čárku a exponent. Specifikátory formátu %g a %G také v tomto formátu v některých případech formátuje čísla. V předchozích verzích by CRT vždy vygeneroval řetězce s tříciferným exponentem. Například by
printf("%e\n", 1.0)se vytiskla 1,000000e+000, což bylo nesprávné. Jazyk C vyžaduje, aby v případě, že je exponent reprezentovatelný pouze pomocí jedné nebo dvou číslic, byly vytištěny pouze dvě číslice.V Visual Studio 2005 byl přidán přepínač globální shody: _set_output_format. Program může tuto funkci volat s argumentem _TWO_DIGIT_EXPONENT, aby byl umožněn odpovídající tisk exponentu. Výchozí chování se změnilo na režim exponentu tisku, který vyhovuje standardům.
Formátování ověření řetězce
V předchozích verzích funkce
printfa bezobslužně přijímaly mnoho neplatných formátovýchscanfřetězců, někdy s neobvyklými účinky. Například %hlhld se bude považovat za %d. Všechny neplatné formátovací řetězce se teď zachází jako s neplatnými parametry.Ověření řetězce v režimu fopen
V předchozích verzích rodina
fopenfunkcí bezobslužně přijala některé řetězce neplatného režimu, napříkladr+b+. Zjistily se neplatné řetězce režimu a zachází se s nimi jako s neplatnými parametry._O_U8TEXT režimu
Funkce _setmode teď správně hlásí režim pro datové proudy otevřené in_O_U8TEXT režimu. V předchozích verzích knihovny by takové datové proudy hlásit jako otevřené v _O_WTEXT.
Tato změna způsobuje chyby, pokud váš kód interpretuje _O_WTEXT datových proudů, ve kterých je kódování 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
Teď jsou implementované funkce snprintfa vsnprintf. Starší kód často poskytoval definice verzí maker těchto funkcí, protože nebyly implementovány knihovnou CRT, ale v novějších verzích už nejsou potřeba. Pokud je soubor snprintf nebo vsnprintf definován jako makro před zahrnutím souboru stdio.h, kompilace nyní selže s chybou, která indikuje, kde bylo makro definováno.
Za normálních okolností je oprava tohoto problému 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 a vygenerovala názvy souborů v kořenovém adresáři
tmpnamtmpnam_sjednotky (například \sd3c.). Tyto funkce teď generují použitelné cesty k názvům souborů v dočasném adresáři.Zapouzdření FILE
V předchozích verzích byl kompletní typ FILE definovaný veřejně v souboru stdio.h, takže se uživatelský kód dostal do souboru FILE a upravl <> jeho vnitřní hodnoty. Knihovna byla změněna tak, aby skryla podrobnosti implementace. V rámci této změny je soubor FILE definovaný v souboru stdio.h neprůhledným typem a jeho členy jsou nepřístupné mimo <> samotný crt.
_outp a _inp
Funkce _outp, _outpw, _outpd,_inp,_inpwa _inpd byly odebrány.
<stdlib.h >< ,ococ.h > a < sys/stat.h>
strtof a wcstof
Funkce
strtofawcstofse nepodařilo nastavit naerrnoERANGE, pokud hodnota nebyla reprezentovatelná jako float. Tato chyba byla specifická pro tyto dvě funkce. Funkce , , astrtodwcstodnebylystrtoldwcstoldovlivněny. Tento problém se opravili a jedná se o změnu modulu runtime, která narušování provozu.Zarovnané funkce přidělování
V předchozích verzích byly zarovnané alokační funkce (
_aligned_malloc_aligned_offset_malloc, atd.) by mohla tiše přijímat požadavky na blok s zarovnáním 0. Požadované zarovnání musí být mocninou hodnoty 2, která nemá hodnotu true nula. Požadované zarovnání 0 se teď považuje za neplatný parametr. Tento problém byl opraven a je zásadní změnou v modulu runtime.Funkce haldy
_heapaddFunkce,_heapseta byly_heapusedodebrány. tyto funkce nebyly funkční, protože CRT byla aktualizována, aby používala haldu Windows.smallheap
smallheapMožnost propojení byla odebrána. Viz Možnosti odkazů.
<String. h>
wcstok
Signatura
wcstokfunkce se změnila tak, aby odpovídala hodnotám, které vyžaduje standard jazyka C. V předchozích verzích knihovny byl podpis této funkce:wchar_t* wcstok(wchar_t*, wchar_t const*)Používá interní kontext pro vlákno ke sledování stavu napříč voláními, jak je provedeno pro
strtok. Funkce má nyní signaturuwchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**)a vyžaduje volajícímu předat kontext jako třetí argument funkce._wcstokK usnadnění přenosu bylo přidáno nové funkce s původním podpisem. Při kompilování kódu jazyka C++ existuje také vložené přetíženíwcstok, které má starý podpis. Toto přetížení je deklarováno jako zastaralé. V kódu jazyka C můžete define_CRT_NON_CONFORMING_WCSTOK, aby se mohl_wcstokpoužít místowcstok.
<Time. h>
clock
v předchozích verzích byla funkce clock implementována pomocí rozhraní Windows API GetSystemTimeAsFileTime. V této implementaci byla funkce hodin citlivá na systémový čas, a proto nebyla nutně monotónní. Funkce Clock se znovu implementovala z podmínek QueryPerformanceCounter a teď je monotónní.
fstat a _utime
V předchozích verzích funkce _stat, fstata _utime zpracovávají letní čas nesprávně. před Visual Studio 2013 všechny tyto funkce nesprávně upravily standardní časové časy, jako kdyby byly v letním čase.
v Visual Studio 2013 byl problém vyřešen v _stat rodině funkcí, ale podobné problémy v fstat_utime a rodinám funkcí nebyly opraveny. Tato částečná oprava vedla k problémům z důvodu nekonzistence mezi funkcemi. Fstat a _utime řady funkcí byly nyní opraveny, takže všechny tyto funkce nyní zpracovávají letní čas správně a konzistentně.
asctime
V předchozích verzích asctime funkce odvolala jednociferné číslo dnů s úvodní nulou, například: . Specifikace vyžaduje, aby tyto dny byly doplněny na úvodní místo, jako v
Fri Jun 6 08:00:00 2014. Tento problém byl opraven.strftime a wcsftime
strftimeFunkce awcsftimeteď podporují specifikátory formátu% C,% D,% e,% F,% g,% g,% h,% n,% r,% t,% t,% u a% V. Kromě toho modifikátory E a O jsou analyzovány, ale ignorovány.Specifikátor formátu% c je zadán jako označení "vhodné reprezentace data a času" pro aktuální národní prostředí. V národním prostředí jazyka C musí být tato reprezentace shodná se stejným
%a %b %e %T %Yformulářem, jako je vytvořenaasctime. V předchozích verzích specifikátor formátu% c nesprávně formátované časy pomocíMM/DD/YY HH:MM:SSreprezentace. Tento problém byl opraven.timespec a TIME_UTC
<Hlavička Time. h > nyní definuje
timespectyp atimespec_getfunkci z C11 Standard. Kromě toho je nyní definováno makro TIME_UTC pro použití stimespec_getfunkcí. Tato aktualizace je zásadní změnou kódu, který má konfliktní definici pro některý z těchto identifikátorů.CLOCKS_PER_SEC
Makro CLOCKS_PER_SEC se teď rozšíří na celé číslo typu
clock_t, jak to vyžaduje jazyk C.
Standardní knihovna C++
Pokud byte chtěli povolit nové optimalizace a kontroly ladění, implementace standardní knihovny C++ záměrně neumožňuje binární kompatibilitu mezi verzemi. 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í. Takovéto směšování objektů 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 detekovat kombinování knihoven DLL a nemůže rozpoznat smíchání, která zahrnuje Visual Studio 2008 nebo starší.
Soubory zahrnutí standardní knihovny C++
Některé změny byly provedeny ve struktuře include v hlavičkách standardní knihovny jazyka C++. Hlavičky standardní knihovny jazyka C++ můžou zahrnovat jiné neurčené způsoby. Obecně byste měli napsat kód tak, aby pečlivě zahrnoval všechny hlavičky, které potřebuje podle standardu jazyka C++, a nespoléhá se na to, které hlavičky standardní knihovny jazyka C++ obsahují další hlavičky standardní knihovny jazyka C++. Díky tomu je kód přenosný napříč různými verzemi a platformami. minimálně dvě změny hlaviček v Visual Studio 2015 ovlivňují uživatelský kód. Za prvé <> už řetězec neobsahuje < iterátor > . Za druhé, < řazené kolekce členů > nyní deklaruje
std::arraybez zahrnutí všech < polí > , což může přerušit kód prostřednictvím následující kombinace konstrukcí kódu: váš kód má proměnnou s názvem "Array" a máte pomocí oboru názvů std; standardní knihovnu jazyka C++ (například < funkce), která >< nyní deklaruje položku s řazenou kolekcí členů >std::array.steady_clock
<Chrono > implementace < se změnila tak, aby splňovala standardní požadavky C++ pro Steadiness a monotonicity.
steady_clockje nyní založen nasteady_clockahigh_resolution_clockje nyní definicí prosteady_clock. v důsledku toho je v Visual Studiosteady_clock::time_pointnyní definice typu prochrono::time_point<steady_clock>; to však není nutně případ pro jiné implementace.přidělování a const
Pro přijetí argumentů const na obou stranách teď vyžadujeme porovnání rovnosti a nerovnosti přidělování. Pokud vaše přidělování definují tyto operátory jako toto,
bool operator==(const MyAlloc& other)pak byste je měli aktualizovat a deklarovat jako členy const:
bool operator==(const MyAlloc& other) constelementy const
Standard C++ má vždycky zakázané kontejnery elementů const (jako je Vector < const t > nebo Set < const t > ). Visual Studio 2013 a dříve přijaly takové kontejnery. V aktuální verzi nelze tyto kontejnery zkompilovat.
std:: přidělování::d eallocate
v Visual Studio 2013 a starších verzích
std::allocator::deallocate(p, n)ignoruje argument předaný prostd::allocator::deallocate(p, n). Standard jazyka C++ vždy vyžaduje, aby hodnota n musela být rovna hodnotě předané jako první argument vyvolání, které vrátilo hodnotu p. V aktuální verzi je však zkontrolována hodnota n . Kód, který předává argumenty pro n , které se liší od toho, co vyžaduje standard, může za běhu selhat.hash_map a hash_set
nestandardní soubory hlaviček < hash_map > a < hash_set > jsou v Visual Studio 2015 zastaralé a v budoucí verzi se odeberou. <> Místo toho použijte unordered_map a < unordered_set > .
komparátorů a – operátor ()
Asociativní kontejnery ( <> rodina map) nyní vyžadují, aby jejich komparátorů měly operátory volání funkce, které lze volat jako const. Následující kód v deklaraci třídy komparátor nyní nemůže kompilovat:
bool operator()(const X& a, const X& b)Chcete-li tuto chybu vyřešit, změňte deklaraci funkce na:
bool operator()(const X& a, const X& b) constvlastnosti typu
Odebrali jste staré názvy vlastností typu z dřívější verze konceptu jazyka C++. tyto změny byly změněny v c++ 11 a byly aktualizovány na hodnoty c++ 11 v Visual Studio 2015. V následující tabulce jsou uvedeny staré a nové názvy.
Starý název Nové jméno add_reference add_lvalue_reference has_default_constructor is_default_constructible has_copy_constructor is_copy_constructible has_move_constructor is_move_constructible has_nothrow_constructor is_nothrow_default_constructible has_nothrow_default_constructor is_nothrow_default_constructible has_nothrow_copy is_nothrow_copy_constructible has_nothrow_copy_constructor is_nothrow_copy_constructible has_nothrow_move_constructor is_nothrow_move_constructible has_nothrow_assign is_nothrow_copy_assignable has_nothrow_copy_assign is_nothrow_copy_assignable has_nothrow_move_assign is_nothrow_move_assignable has_trivial_constructor is_trivially_default_constructible has_trivial_default_constructor is_trivially_default_constructible has_trivial_copy is_trivially_copy_constructible has_trivial_move_constructor is_trivially_move_constructible has_trivial_assign is_trivially_copy_assignable has_trivial_move_assign is_trivially_move_assignable has_trivial_destructor is_trivially_destructible spustit:: Any a Launch:: Sync – zásady
Nestandardní
launch::anyalaunch::synczásady byly odebrány. Místo toholaunch::anypoužijtelaunch:async | launch:deferred. Prolaunch::syncpoužijtelaunch::deferred. Viz Spustit výčet.
Rozhraní MFC a knihovna ATL
Knihovna MFC (Microsoft Foundation Classes)
už není součástí typické instalace Visual Studio z důvodu velké velikosti. chcete-li nainstalovat knihovnu MFC, zvolte možnost vlastní instalace v nastavení Visual Studio 2015. pokud již máte nainstalován Visual Studio 2015, můžete knihovnu MFC nainstalovat spuštěním Visual Studio instalaci znovu. Zvolte možnost vlastní instalace a pak zvolte položku Microsoft Foundation Classes. instalaci Visual Studio můžete spustit pomocí ovládacího paneluprogramy a funkcenebo z instalačního média nástroje.
Distribuovatelný balíček Visual C++ stále zahrnuje i tuto knihovnu.
Concurrency Runtime
dej makro z Windows. h koliduje s concurrency:: Context:: Yield
Concurrency Runtime dříve použili
#undefk zrušení definice makra yield, aby nedocházelo ke konfliktům mezi makrem yield definovaným v Windows. h h aconcurrency::Context::Yieldfunkcí. Toto#undefbylo odebráno a bylo přidáno nové Nekolidující ekvivalentní volání rozhraní API#undef. Chcete-li vyřešit konflikty s výsledkem, můžete buď aktualizovat kód pro voláníYieldExecutionfunkce, nebo obklopitYieldnázev funkce pomocí závorek na webech volání, jako v následujícím příkladu:(concurrency::Context::Yield)();
vylepšení shody kompilátoru v Visual Studio 2015
při upgradu kódu z předchozích verzí může dojít také k chybám kompilátoru, které jsou způsobeny vylepšeními shody provedenými v Visual Studio 2015. tato vylepšení neruší binární kompatibilitu z dřívějších verzí Visual Studio, ale mohou způsobit chyby kompilátoru, kde žádná nebyla vygenerována dříve. Další informace najdete v tématu Visual C++ novinky 2003 až 2015.
v Visual Studio 2015 mohou průběžná vylepšení shody kompilátoru někdy měnit způsob, jakým kompilátor rozumí vašemu existujícímu zdrojovému kódu. V důsledku toho může dojít k výskytu nových nebo různých chyb během sestavení nebo dokonce i rozdílů v kódu, které dříve sestavily a zdály se pracovat správně.
Naštěstí tyto rozdíly mají malý nebo žádný vliv na většinu vašeho zdrojového kódu. V případě, že je pro vyřešení těchto rozdílů nutný zdrojový kód nebo jiné změny, jsou opravy velmi malé a musí být přímo předávány. Zahrnuli jsme spoustu příkladů dříve přijatelného zdrojového kódu, který může být potřeba změnit (před) , a opravy, které je třeba opravit (po).
i když tyto rozdíly mohou ovlivnit váš zdrojový kód nebo jiné artefakty sestavení, nemají vliv na binární kompatibilitu mezi aktualizacemi Visual Studio verzí. zásadní změna je přísnější a může mít vliv na binární kompatibilitu, ale k těmto typům binárních rozdílů se dochází pouze mezi hlavními verzemi Visual Studio, například mezi Visual Studio 2013 a Visual Studio 2015. informace o nejnovějších změnách, ke kterým došlo mezi Visual Studio 2013 a Visual Studio 2015, najdete v článku změny shody Visual Studio 2015.
vylepšení shody v Visual Studio 2015
/Zc: forScope-Option
Možnost kompilátoru
/Zc:forScope-je zastaralá a v budoucí verzi se odebere.Command line warning D9035: option 'Zc:forScope-' has been deprecated and will be removed in a future releaseObvykle se tato možnost použila, aby povolovala nestandardní kód, který používá proměnné smyčky za bodem, kde, podle standardu, by měl být mimo rozsah. Bylo nutné pouze v případě, že jste kompilujei s
/Zamožností, od bez/Zapoužití proměnné for Loop po konci smyčky je vždy povoleno. Pokud si nejste jisti dodržováním standardů (například pokud váš kód není určen pro přenos do jiných kompilátorů), můžete vypnout/Zamožnost (nebo nastavit vlastnost/Zana hodnotu ne). Pokud se postará o zápis přenosného kódu, který vyhovuje předpisům, měli byste přepsat kód tak, aby splňoval Standard, 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átoru/ZgMožnost kompilátoru (generovat prototypy funkce) už není dostupná. Tato možnost kompilátoru byla dřív zastaralá.Nemůžete již spouštět testy jednotek pomocí jazyka C++/CLI z příkazového řádku s mstest.exe. Místo toho použijte vstest.console.exe. Viz Možnosti příkazového řádkuVSTest.Console.exe.
mutable – klíčové slovo
mutableSpecifikátor třídy úložiště již není povolen v místech, kde byla dříve zkompilována bez chyby. Nyní kompilátor poskytuje 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 na názvy deklarované jako const nebo static a nelze je použít pro členy odkazu.Zvažte například následující kód:
struct S { mutable int &r; };Předchozí verze kompilátoru to přijaly, ale teď kompilátor poskytuje tuto chybu:
error C2071: 'S::r': illegal storage classChcete-li chybu opravit, odeberte nadbytečné
mutableklíčové slovo.char_16_t a char32_t
V nástroji už nemůžete používat
char16_tnebochar32_tjako aliasytypedef, protože tyto typy se teď považují za předdefinované. Bylo běžné, že uživatelé a autoři knihoven mají definovatchar16_tachar32_tjako aliasyuint16_ta vuint32_tuvedené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
Určitý kód, který zahrnuje parametry šablony bez typu, je nyní správně zkontrolován na kompatibilitu typu při zadání explicitních argumentů šablony. Například následující kód byl zkompilován bez chyby v předchozích verzích 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ě poskytuje chybu, protože typ parametru šablony neodpovídá argumentu šablony (parametr je ukazatel na konstantní člen, 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'Chcete-li vyřešit tuto chybu ve vašem kódu, ujistěte se, že typ argumentu šablony, který použijete, odpovídá deklarovanému typu parametru šablony.
__declspec(align)Kompilátor již nepřijímá
__declspec(align)funkce. Tento konstruktor se vždycky ignoruje, ale teď 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 nedošlo k žádnému vlivu, odebrání nemění nic.Zpracování výjimek
Zpracovávání výjimek je několik změn. Nejprve objekty výjimky musí být buď kopírovací, nebo pohyblivý. Následující kód je zkompilován Visual Studio 2013, ale v roce 2015 se Visual Studio nezkompiluje:
struct S { public: S(); private: S(const S &); }; int main() { throw S(); // error }Problém je v tom, že kopírovací konstruktor je soukromý, takže objekt nelze zkopírovat tak, jak k tomu dochází v běžném průběhu zpracování výjimky. Totéž platí, když je konstruktor kopírování
explicitdeklarován.struct S { S(); explicit S(const S &); }; int main() { throw S(); // error }Pokud chcete aktualizovat kód, ujistěte se, že kopírovací konstruktor pro váš objekt výjimky je a
publicnení označenexplicit.Zachycení výjimky podle hodnoty také vyžaduje, aby byl objekt výjimky kopírovatelný. Následující kód je zkompilován Visual Studio 2013, ale v roce 2015 se Visual Studio nezkompiluje:
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 pro
catchna odkaz.catch (D& d) { }Řetězcové literály následované makly
Kompilátor teď podporuje uživatelsky definované literály. V důsledku toho jsou řetězcové literály následované makru bez jakýchkoli intervenovaných prázdných znaků interpretovány jako literály definované uživatelem, což může způsobit chyby nebo neočekávané výsledky. 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" následovaný makru, které je rozbalené na "there" a pak byly dva řetězcové literály zřetězovány do jednoho. V Visual Studio 2015 interpretuje kompilátor tuto sekvenci jako literál definovaný uživatelem, ale vzhledem k tomu, že není definován žádný odpovídající uživatelsky definovaný literál, dojde k
_xchybě.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?Pokud chcete 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 kvůli souvisejícím změnám v parsování řetězců sousední řetězcové literály (literály širokého nebo úzkého znakového řetězce) bez prázdných znaků interpretují v předchozích verzích visaul C++ jako jeden zřetězovaný řetězec. V Visual Studio 2015 teď musíte mezi tyto dva řetězce přidat prázdné znaky. Například je třeba změnit 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";Umístění nové a odstranění
Operátor se změnil, aby byl v souladu se
deletestandardem C++14. Podrobnosti o změně standardů najdete na adrese C++ Sized Deallocation. Změny přidávají formu globálníhodeleteoperátoru, který přebírá parametr velikosti. Změna narušuje chybu v tom, že pokud jste dříve používali operátor se stejným podpisem (aby odpovídal operátoru umístění new), zobrazí se chyba kompilátorudelete(C2956, ke které dochází v místě, kde se používá nové umístění, protože to je pozice v kódu, kde se kompilátor pokouší identifikovat odpovídajícídeletedeleteoperátor).Funkce byla
void operator delete(void *, size_t)void operator delete(void *, size_t)odpovídající nové funkci umístění v jazyce C++11. U navracení s velikostí C++14 je teď tato funkce delete obvyklou funkcí navracení (globální operátor). Standard vyžaduje, aby v případě, že použití nového umístění vyhledá odpovídající funkci delete a najde obvyklou funkci navracení, bude program špatně formátovaný.Předpokládejme například, že váš kód definuje nové umístění i odstranění umístění:
void * operator new(std::size_t, std::size_t); void operator delete(void*, std::size_t) noexcept;K tomuto problému dochází kvůli shodě v signaturách funkce mezi operátorem odstranění umístění, který jste definovali, a novým operátorem globální velikosti. Zvažte, zda lze použít jiný typ než pro jakékoli umístění nové a
size_tsize_tdeleteoperátory. Typ jesize_ttypedefzávislý na kompilátoru; je totypedefpro vunsigned intMSVC. Dobrým řešením je použít výčtový typ, například tento:enum class my_type : size_t {};Pak změňte definici umístění new a na použití tohoto typu jako druhého argumentu místo
size_t. Budete také muset aktualizovat volání do umístění new, aby bylo možné předat nový typ (například pomocí metody k převodu z celočíselné hodnoty) a aktualizovat definici a tak, aby se přetypová styp přetypováal zpět nastatic_cast<my_type>newdeleteceločíselný typ. Pro tento typ není nutné používat ; bude fungovat také typ třídy senumsize_tčlenem.Alternativním řešením je, že můžete zcela eliminovat nové umístění. Pokud váš kód používá umístění new k implementaci fondu paměti, kde argument umístění je velikost přidělovaný nebo odstraněný objekt, pak funkce přidělení velikosti může být vhodná k nahrazení vlastního kódu fondu paměti a můžete se zbavit funkcí umístění a místo funkcí umístění použít vlastní operátor vracení dvou argumentů.
Pokud nechcete aktualizovat kód okamžitě, můžete se vrátit ke starému chování pomocí možnosti kompilátoru
/Zc:sizedDealloc-. Pokud použijete tuto možnost, funkce odstranění se dvěma argumenty neexistují a nezpůsobí konflikt s operátorem odstranění umístění.Datové členy sjednocené sjednocené
Datové členy sjednocené typy už nemají odkazové typy. Následující kód se úspěšně zkompiloval v Visual Studio 2013, ale v roce 2015 Visual Studio chybu.
union U1 { const int i; }; union U2 { int & i; }; union U3 { struct { int & i; }; };Předchozí kód vyprodukuje 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á sjednocené pole. Změna kódu na hodnotu by změnila data uložená v sjednocené sjednocené paměti, což má vliv na ostatní pole, protože pole v typech sjednocené paměti sdílejí stejnou paměť. V závislosti na velikosti hodnoty může také změnit velikost sjednocené hodnoty.
Anonymní sjednocená připojení jsou teď více v souladu se standardem. Předchozí verze kompilátoru generují explicitní konstruktor a destruktor pro anonymní sjednocená rozhraní. Tyto funkce generované kompilátorem se ve Visual Studio 2015 odstraní.
struct S { S(); }; union { struct { S s; }; } u; // C2280Předchozí kód vygeneruje následující chybu v Visual Studio 2015:
error C2280: '<unnamed-type-u>::<unnamed-type-u>(void)': attempting to reference a deleted function note: compiler has generated '<unnamed-type-u>::<unnamed-type-u>' 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 chování modulu runtime odpovídalo standardu, změnilo se chování členů anonymních struktur ve sjednocených formátech. Konstruktor pro členy anonymní struktury ve sjednocené struktury již není implicitně volán při vytvoření takového sjednocení. Destruktor pro členy anonymní struktury ve sjednocené struktuře už není implicitně volán, když sjednocené rozhraní přejde mimo rozsah. Vezměme si následující kód, ve kterém sjednocené číslo U obsahuje anonymní strukturu, která obsahuje pojmenovanou členovou 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; }V Visual Studio 2013 je při vytvoření sjednoceného sjednoceného volání volán konstruktor pro S a destruktor pro S je volán při vyčištění zásobníku funkce f. V Visual Studio 2015 ale konstruktor a destruktor nejsou volány. 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 calledPokud chcete obnovit původní chování, zadejte název anonymní struktury. Chování ne anonymních struktur za běhu 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; }Alternativně zkuste do nových funkcí přesouvat kód konstruktoru a destruktoru a přidat volání těchto funkcí z konstruktoru a destruktoru pro sjednocené rozhraní.
#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; }Řešení šablon
Byly provedeny změny překladu názvů pro šablony. V jazyce C++ může být při zvažování kandidátů pro překlad názvu případ, že jeden nebo více zvážení názvů, protože potenciální shody vytvoří neplatnou instanci šablony. Tyto neplatné instance obvykle nezpůsobí chyby kompilátoru, princip označovaný jako SFINAE (selhání nahrazení není chyba).
Pokud teď SFINAE vyžaduje, aby kompilátor vytvoří instanci specializace šablony třídy, všechny chyby, ke kterým došlo 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); }Při kompilaci s aktuálním kompilátorem se zobrazí 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 ]Je to proto, že v okamžiku prvního vyvolání is_base_of třída
Dještě nebyla definována.V tomto případě je opravou nepou ít takové vlastnosti typu, dokud není definována třída . Pokud přesunete definice a na začátek souboru
BDkódu, chyba se vyřeší. Pokud jsou definice v souborech hlaviček, zkontrolujte pořadí příkazů zahrnutí pro soubory hlaviček a ujistěte se, že jsou před použitím problematických šablon zkompilovány všechny definice tříd.Kopírovací konstruktory
V Visual Studio 2013 i Visual Studio 2015 kompilátor vygeneruje konstruktor kopírování pro třídu, pokud tato třída má uživatelem definovaný konstruktor přesunutí, ale žádný uživatelem definovaný konstruktor kopírování. Ve vývojáři Dev14 je tento implicitně vygenerovaný konstruktor kopírování také označen jako "= delete".
Main deklarovaný jako externí "C" teď 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(){} // OKTypename není v inicializátoru členu 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,
typenameodeberte z inicializátoru:S1() : T::type() // OK ...Třída úložiště při explicitních specializacích je ignorována.
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_assertse vždy nezdaří:template <size_t some_value> struct S1 { static_assert(false, "default not valid"); // always invoked }; //other partial specializations herePokud chcete tento problém obvyř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 dopředné deklarace. (Platí pouze pro jazyk 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 identifierPokud chcete tento problém vyřešit, přidejte správné dopředné 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ů na funkci
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 teď vytvoří 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 } };Pokud chcete chybu opravit, můžete plně kvalifikovat volání
bind: N::bind(...). Pokud je však tato změna manifestována prostřednictvím nedeklarovaný identifikátor (C2065), může být vhodné tento problém opravitusingdeklarací.K tomuto vzoru často dochází u ComPtr a dalších typů v oboru
Microsoft::WRLnázvů .Oprava nesprávné adresy
Následující kód teď vytvoří C2440: '=': nelze převést z 'type *' na 'type'. Pokud chcete chybu opravit, & změň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 teď 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 , jinak změňte text souboru tak, aby
const void*vypadal jako v tomtohpříkladu:void h(void) { char name[] = __FUNCTION__; f( name); void *p = &""; }Řetězce UDL jazyka C++11
Následující kód teď vyprodukuje chybu C3688: neplatná přípona literálu L. Operátor literal nebo šablona operátoru literálu "operátor ""L" se nenašla
#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 vyřešit, změňte kód tak, aby se přidá mezera:
#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říkladu výše
MACROse už ne parsuje jako dva tokeny (řetězec následovaný makru). Teď se parsuje jako UDL s jedním tokenem. Totéž platí pro L"L", které se dříve parsoval jako L a L" a teď se parsuje jako L"""L a "".Pravidla zřetězení řetězců se také přenesla do souladu se standardem, což znamená, že L"a" "b" odpovídá L"ab". Předchozí edice Visual Studio nepřijaly zřetězení řetězců s různou šířkou znaků.
Odebrání prázdného znaku C++11
Následující kód teď vytvoří 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 byl null explicitní:
bool check(wchar_t c){ return c == L'\0'; }Výjimky MFC nelze zachytát hodnotou , protože se nekopírují.
Následující kód v aplikaci MFC teď způsobí chybu C2316: 'D': nelze zachytát, protože destruktor nebo kopírovací konstruktor jsou nedostupné 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 změnit blok catch na , ale lepším řešením je obvykle použití maker
catch (const D &)MFC TRY/CATCH.je teď klíčové slovo
Následující kód teď vyprodukuje chybu C2332: 'class': missing tag name. Pokud chcete kód opravit, musíte přejmenovat třídu nebo , pokud třída provádí stejnou práci jako , stačí nahradit
alignoftřídu klíčovým slovem new.class alignof{}je teď klíčové slovo
Následující kód teď vyprodukuje chybu C2059: chyba syntaxe: ')'. Pokud chcete kód opravit, musíte přejmenovat všechny funkce nebo názvy proměnných, které jsou volány
constexpr.int constexpr() {return 1;}Vyměnitelné typy nemůže být const
Pokud funkce vrátí typ, který má být přesunut, její návratový typ by neměl být
const.Odstraněné konstruktory kopírování
Následující kód teď vytvoří C2280 S::S(S):: pokusí 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 vyřešit, 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 byl vygenerován pouze v případě, že nejsou zaznamenány žádné výrazy lambda.
Následující kód vytvoří C2664 v 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 teď vyprodukuje chybu C2440: 'přetypování': 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ě zavolejte 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 teď 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ě zavolejte operátor převodu:
void f(S1 *p, S2 s) { *p = s.operator S1&(); }Oprava neplatné inicializace kopírování v inicializaci nestatické datového členu (NSDMI)
Následující kód teď vyprodukuje chybu C2664: 'S1::S1(S1 )': nemůže převést && argument 1 z 'bool' na 'const S1 & ':
struct S1 { explicit S1(bool); }; struct S2 { S1 s2 = true; // error };Pokud chcete chybu vyřešit, 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 teď vytvoří C2248: 'S::S': nemůže přistupovat k privátnímu členu deklarovaným ve třídě 'S':
class S { S(); public: int i; }; class S2 { auto f() -> decltype(S().i); };Pokud chcete tuto chybu vyřešit, přidejte v deklaraci friend
S2proS: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 teď vyprodukuje chybu C3497: nelze vytvořit instanci lambda:
void func(){ auto lambda = [](){}; decltype(lambda) other; }Pokud chcete chybu opravit, odeberte potřebu volání výchozího konstruktoru. Pokud lambda nic nezachytí, může být přetypován na ukazatel funkce.
Výrazy lambda s odstraněnou operátorem přiřazení
Následující kód teď vyprodukuje 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 functor nebo odeberte potřebu použití operátoru přiřazení.
Pokus o přesunutí objektu s odstraněný kopírovací konstruktor
Následující kód teď vyprodukuje chybu C2280: moveable::moveable(const moveable ): pokus o odkazování & 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 tuto chybu vyřešit, 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 teď vyprodukuje chybu C2079: s používá nedefinované struktury main::S2.
int main() { struct S2; struct S1 { void f() { S2 s; } }; struct S2 {}; }Pokud chcete tuto chybu vyřešit, přejděte o definici
S2:int main() { struct S2 { //moved up }; struct S1 { void f() { S2 s; } }; }Nelze volat chráněný základní objekt v těle odvozeného ctoru.
Následující kód teď vyprodukuje chybu C2248: 'S1::S1': nemůže přistupovat k chráněnému členu deklarované ve třídě 'S1'
struct S1 { protected: S1(); }; struct S2 : public S1 { S2() { S1(); } };Pokud chcete chybu opravit, odeberte z konstruktoru volání metody a v případě potřeby
S2S1()ji dejte do jiné funkce.zabraňuje převodu na ukazatel
Následující kód teď vytvoří C2439 S::p: člen se neinicializoval.
struct S { S() : p({ 0 }) {} void *p; };Pokud chcete chybu vyřešit, odeberte složené závorky z okolí nebo použijte místo toho
0nullptr, jak je znázorněno v tomto příkladu:struct S { S() : p(nullptr) {} void *p; };Nesprávná definice makra a jejich použití pomocí závorek
Následující příklad teď vyprodukuje chybu C2008: ';': neočekávané v definici makra
#define A; //cause of error struct S { A(); // error };Pokud chcete problém vyřešit, změňte horní řádek na .
#define A();Následující kód vyprodukuje chybu C2059: chyba syntaxe: ')'
//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 vyprodukuje chybu C2091: funkce vrací funkci :
#define DECLARE void f() struct S { DECLARE(); };Pokud chcete tuto chybu vyřešit, odeberte závorky za DECLARE v S:
DECLARE;.Následující kód vyprodukuje chybu C2062: neočekávaný typ int
#define A (int) struct S { A a; };Pokud chcete problém vyřešit,
Adefinujte ho tímto kódem:#define A intExtra parens v deklaracích
Následující kód vyprodukuje chybu C2062: neočekávaný typ int
struct S { int i; (int)j; };Pokud chcete chybu vyřešit, odeberte závorky kolem
j. Pokud jsou závorky potřeba pro přehlednost, použijtetypedef.Konstruktory generované kompilátorem a __declspec (listopadtable)
V Visual Studio 2015 existuje zvýšená pravděpodobnost, že kompilátorem generované vložené konstruktory abstraktních tříd s virtuálními základními třídami mohou při použití v kombinaci s vystavit nesprávné použití
__declspec(novtable)__declspec(dllimport)třídy .auto vyžaduje při inicializaci direct-list-initialization jeden výraz.
Následující kód teď vyprodukuje chybu C3518: 'testPositions': v kontextu direct-list-initialization 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
testPositionsinicializace ná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ů vs. ukazatelů na typy is_convertible
Následující kód teď způsobí selhání statického kontrolního výrazu.
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 s aDB2:static_assert(std::is_convertible<D*, B2*>::value, "fail");__declspec (listopadtable) musí být konzistentní.
__declspecDeklarace musí být konzistentní napříč všemi knihovnami. Následující kód teď vytvoří porušení pravidla s jednou definicí://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 nepřímo odvozených
private virtualzákladních tříd. 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žnily operátoru bez členu new a non-member operátor delete deklarovat jako statický a deklarovaný v jiných oborech názvů než globální obor názvů. Toto staré chování vyvolalo riziko, že program nebude volat implementaci operátoru nebo, kterou programátor zamýšlel, což vedlo k tichému
newdeletešpatnému 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 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, je včleněný operátor
newpovažován za nesprávně vytvořený.Volání operátoru ' Type() ' (uživatelsky definovaný převod) na typy bez třídy
Předchozí verze povoleného kompilátoru ' operator Type() ', které mají být volány na typy bez třídy, zatímco jsou tiše ignorovány. Toto staré chování vytvořilo riziko tichého chybného generování kódu, což vede k nepředvídatelnému chování za běhu. Kompilátor již nepřijímá kód napsaný tímto způsobem a namísto toho vydá 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í TypeName v propracované specifikátorech typu
Předchozí verze kompilátoru jsou povoleny ve vytvořeném
typenamespecifikátoru typu, ale kód napsaný tímto způsobem je sémanticky nesprávným. Kompilátor již nepřijímá kód napsaný tímto způsobem a namísto toho vydá 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;Typ srážek polí ze seznamu inicializátorů
Předchozí verze kompilátoru nepodporovaly typ srážek polí ze seznamu inicializátorů. Kompilátor teď podporuje tento typ odvození typu, a proto volání šablon funkcí pomocí seznamů inicializátorů teď může být dvojznačné nebo jiné přetížení může být zvolené než v předchozích verzích kompilátoru. Aby bylo možné tyto problémy vyřešit, musí nyní program explicitně určit přetížení, které programátor zamýšlel.
V případě, že toto nové chování způsobí, že řešení přetížení považuje další kandidáty, které jsou stejně vhodné jako historické kandidáty, volání se nejednoznační a kompilátor vyvolá chybu kompilátoru C2668 v důsledku.
error C2668: 'function' : ambiguous call to overloaded function.Příklad 1: dvojznačné volání funkce přetížení (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 (po)
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); }V případě, že toto nové chování způsobí, že při přetěžování dojde k zvážení dalšího kandidáta, který je lepší, než historický kandidát, volání se jednoznačně vyřeší na novém kandidáta, což způsobí změnu v chování programu, která je pravděpodobně odlišná od zamýšleného programátora.
Příklad 2: Změna v řeš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 v řešení 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á obnovená upozornění a upozornění související s konkrétními případy (včetně výchozího případu) jsou nyní vydány na řádku obsahujícím problematický případ, nikoli na posledním řádku příkazu switch. V důsledku toho, že teď tato upozornění vydávají na různých řádcích než v minulosti, už se upozornění, která jste předtím potlačili, už nebudou potlačit#pragma warning(disable:####). Chcete-li potlačit tato upozornění jako zamýšlená, může být nutné přesunout#pragma warning(disable:####)direktivu na řádek nad první problematický případ. Obnoví se následující 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 (za)
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 dokumentaci.
#include: použití specifikátoru nadřazeného adresáře '.. ' v cestě (týká se jenom
/Wall/WX)Předchozí verze kompilátoru nerozpoznaly použití specifikátoru nadřazeného adresáře... v cestě k
#includedirektivám. Kód psaný tímto způsobem je obvykle určen pro zahrnutí hlaviček, které existují mimo projekt, pomocí nesprávného použití relativních cest projektu. Toto staré chování vytvořilo riziko, že program může být zkompilován zahrnutím jiného zdrojového souboru, než je programátor zamýšlen, nebo zda tyto relativní cesty nebudou přenosné do jiných prostředí pro sestavení. Kompilátor nyní detekuje a upozorňuje programátora kódu napsaného tímto způsobem a vydá volitelné C4464 upozornění kompilátoru, pokud je povoleno.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 directoriesI když kompilátor neposkytuje konkrétní diagnostiku, doporučujeme také, aby specifikátor nadřazeného adresáře ".." neměl být použit k určení adresáře include projektu.
#pragma optimize () rozšiřuje poslední konec souboru hlaviček (týká se jenom
/WX).Předchozí verze kompilátoru nerozpoznaly změny nastavení příznaku optimalizace, které řídí hlavičkový soubor zahrnutý do jednotky překladu. Kompilátor nyní detekuje a upozorňuje programátora kódu napsaného tímto způsobem a vydá volitelné upozornění kompilátoru C4426 v umístění problematické
#include, pokud je povoleno. Toto upozornění je vystaveno pouze v případě, že změny jsou v konfliktu s příznaky optimalizace nastavenými argumenty příkazového řádku pro kompilátor.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 upozornění (push) a upozornění #pragma (pop) (týká se jenom )
Předchozí verze kompilátoru nerozpoznaly
#pragma warning(push)změny stavu spárované se#pragma warning(pop)změnami stavu v jiném zdrojovém souboru, což je zřídka zamýšlené. Toto staré chování vytvořilo riziko, že program bude zkompilován s jinou sadou upozornění, než je zamýšlený programátor, což může vést k tichému chybnému chování za běhu. Kompilátor nyní detekuje a upozorňuje programátora kódu napsaného 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 upozornění (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" ...I když je neobvyklá, kód napsaný tímto způsobem je někdy úmyslné. Kód psaný 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í v samostatném způsobu.Upozornění na neshodné #pragma (push) (týká se jenom
/WX)Předchozí verze kompilátoru nezjistily neshodné
#pragma warning(push)změny stavu na konci jednotky překladu. Kompilátor nyní detekuje a upozorňuje programátora kódu napsaného tímto způsobem a vydá volitelné upozornění kompilátoru C5032 v umístění nespárované#pragma warning(push), pokud je povoleno. Toto upozornění je vystaveno 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 (po)
// 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)Další upozornění můžou být vystavena v důsledku vylepšení sledování stavu upozornění #pragma
Předchozí verze kompilátoru sledovány #pragma změny stavu upozornění nedostatečně dobře vydávají všechna zamýšlená upozornění. Toto chování vytvořilo riziko, že určitá upozornění budou efektivně potlačena v jiných případech, než je programátor zamýšlen. Kompilátor nyní sleduje
#pragma warningstav robustnější – zejména v souvislosti se#pragma warningzměnami stavu uvnitř šablon – a volitelně vydá nová upozornění C5031 a C5032, která mají za cíl pomáhat programátorovi 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 se teď můžou vydávat upozornění, která se dřív nesprávně potlačila, nebo upozornění související s dříve nezjištěnými problémy.Vylepšená identifikace nedosažitelného kódu
Změny v knihovně C++ Standard a vylepšená možnost volání vložených funkcí v předchozích verzích kompilátoru může povolit, aby kompilátor prokázal, že je nyní nedosažitelný určitý kód. Toto nové chování může mít za následek nové a více často vydaných instancí upozornění C4720.
warning C4720: unreachable codeV mnoha případech může být toto upozornění vystaveno pouze při kompilaci s povolenými optimalizacemi, protože optimalizace mohou vložit více volání funkce, eliminovat redundantní kód nebo jinak určit, že určitý kód je nedosažitelný. Zjistili jsme, že v blocích try/catch se často objevily nové instance varovných C4720, zejména ve vztahu k použití 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
Další upozornění a chyby mohou být vydány v důsledku částečné podpory pro Expression SFINAE
Předchozí verze kompilátoru neanalyzovaly určité druhy výrazů uvnitř
decltypespecifikátorů z důvodu nedostatku podpory pro Expression SFINAE. Toto staré chování bylo nesprávné a nevyhovuje standardu C++. Kompilátor nyní analyzuje tyto výrazy a má částečnou podporu pro Expression SFINAE z důvodu probíhajících vylepšení dodržování shody. V důsledku toho kompilátor nyní vydá upozornění a chyby nalezené ve výrazech, které předchozí verze kompilátoru neanalyzovaly.Když toto nové chování analyzuje
decltypevýraz, který obsahuje typ, který dosud nebyl deklarován, kompilátor vyvolá chybu kompilátoru C2039 v důsledku.error C2039: 'type': is not a member of 'global namespace'Příklad 1: použití nedeklarované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 (za)
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ítypenameklíčového slova k určení, že se jedná o typ závislého názvu, kompilátor vyvolá upozornění kompilátoru C4346 spolu 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í typu (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> ())); };volatilevolatilePředchozí verze kompilátoru povolily třídu, která má
volatilečlenské proměnné, aby měly výchozí konstruktory Copy/Move a výchozí operátory pro kopírování a přesun se automaticky vygenerovaly. Toto staré chování bylo nesprávné a nevyhovuje standardu C++. Kompilátor nyní považuje třídu, která mávolatilečlenské proměnné, aby měly netriviální operátory konstrukce a přiřazení, což brání automatickému generování výchozích implementací těchto operátorů. Když je taková třída členem sjednocení (nebo anonymního sjednocení uvnitř třídy), konstruktory Copy/Move a operátory přiřazení kopírování a přesunu (nebo třídy obsahující anonymní sjednocení) se implicitně definují jako odstraněné. Pokus o sestavení nebo zkopírování sjednocení (nebo třídy obsahující anonymní sjednocení) bez explicitního definování je chyba a kompilátor vyvolá chybu kompilátoru C2280, která je výsledkem.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í kvalifikátory cv.
předchozí verze Visual Studio 2015 povoleny statických členských funkcí, které mají kvalifikátory cv. k tomuto chování dochází v důsledku regrese v Visual Studio 2015 a Visual Studio 2015 Update 1. Visual Studio 2013 a předchozí verze kompilátoru zamítají kód zapsaný tímto způsobem. chování 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 vygeneruje 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 constDopředná deklarace výčtu není v kódu WinRT povolená (má vliv pouze na )
Kód zkompilovaný pro Windows Runtime (WinRT) neumožňuje předávání typů deklarovaných podobně jako při kompilaci spravovaného kódu C++ pro rozhraní .NET Framework pomocí přepínače
enum/clrkompilátoru. Toto chování zajišťuje, že velikost výčtu je vždy známá a lze ji správně promítovat do systému typů WinRT. Kompilátor odmítne kód napsaný tímto způsobem a vygeneruje 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ý operátor bez členu new a delete operátoru není možné deklarovat jako vložený (úroveň 1 ( ) ve výchozím nastavení je on-by-default).
Předchozí verze kompilátoru nevydá upozornění, pokud jsou funkce new a delete operátoru deklarovány jako vložené. Kód napsaný tímto způsobem je chybně formátovaný (nevyžaduje se žádná diagnostika) a může způsobit problémy s pamětí způsobené neshodou nových a odstraněných operátorů (zejména při použití společně s přidělením velikosti), které může být obtížné diagnostikovat. Kompilátor teď vydá upozornění kompilátoru C4595, které vám pomůže 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, který je napsaný tímto způsobem, může vyžadovat přesunutí definic operátorů ze souboru hlaviček a do odpovídajícího zdrojového souboru.
Vylepšení shody v aktualizaci Update 3
std::is_convertable teď rozpozná vlastní přiřazení (standardní knihovna)
Předchozí verze vlastnosti typu nerozpoznala správně vlastní přiřazení typu třídy při odstranění nebo privátním konstruktoru
std::is_convertablekopírování. Nyní je správně nastavena na při použití nastd::is_convertable<>::valuetyp třídy sfalseodstraněný nebo soukromý kopírovací konstruktor.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 předaly statické kontrolní výrazy v dolní části tohoto příkladu, protože byly
std::is_convertable<>::valuenesprávně nastaveny natrue. Teď jestd::is_convertable<>::valuesprávně nastavená nafalse, což způsobuje selhání statických kontrolních výrazů.Výchozí nebo odstraněné triviální kopírovací a přesouvací konstruktory respektují specifikátory přístupu.
Předchozí verze kompilátoru neschytili specifikátor přístupu výchozího nebo odstraněného triviálního konstruktoru kopírování a přesunutí, než je bylo možné volat. Toto staré chování bylo nesprávné a neodpovídá standardu C++. V některých případech toto staré chování vedlo k riziku tichého špatného generování kódu, což vedlo k nepředvídatelným chováním modulu runtime. Kompilátor teď zkontroluje specifikátor přístupu výchozího nebo odstraněného triviálního konstruktoru kopírování a přesunutí, aby zjistil, jestli se může volat, 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); }Vyrušování podpory kódu ATL s atributy (úroveň 1 ( ) ve výchozím nastavení
Předchozí verze kompilátoru podporovaly kód ATL s atributy. Jako další fáze odebrání podpory pro kód ATL s atributy, který začal v Visual Studio 2008,byl kód ATL s atributy zastaralý. Kompilátor teď vydá upozornění kompilátoru C4467, které vám pomůže 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 se podpora z kompilátoru nezrušuje, můžete toto upozornění zakázat předáním argumentů příkazového řádku nebo kompilátoru nebo přidáním do
/Wv:18/wd:4467#pragma warning(disable:4467)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 můžete potřebovat nebo vytvořit soubor IDL, abyste se vyhnuli používání zastaralých atributů ATL, jako v následujícím příkladu kódu.
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 se ujistili, že jsou generovány definice rozhraní jazyka C++.
Příklad 2 – IDL (po)
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 souboru implementace, jako v příkladu kódu níže.
Příklad 2 Implementace (po)
#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 neshoda #include direktiv (ovlivňuje pouze
/WX)Předchozí verze kompilátoru při použití předkompilovaných souborů hlaviček (PCH) přijímané neshodné direktivy ve zdrojových souborech mezi a
#include-Yc-Yukompilacemi. Takto napsaný kód už kompilátor nepřijímá. Kompilátor teď vydá upozornění kompilátoru CC4598, které vám pomůže identifikovat neshodné direktivy#includepř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 neodpovídající adresáře zahrnutí (mají vliv pouze na
/WX)Předchozí verze kompilátoru při použití předkompilovaných souborů hlaviček
-I-Yc(PCH) přijímaly neshodu argumentů příkazového řádku include adresáře (-Yu). Takto napsaný kód už kompilátor nepřijímá. Kompilátor teď vydá upozornění kompilátoru CC4599, které vám pomůže identifikovat neshodu argumentů příkazového řádku adresáře include (-I).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
Visual Studio 2013 změn v souladu s požadavky
Compiler
Klíčové slovo final teď vygeneruje chybu nerozpoznaných symbolů, kde by bylo dříve zkompilované:
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 voláním, ale program se za běhu
virtualchybově zhroucoval. Nyní je přiřazena chyba linkeru, protože třída je nyní označena jako konečná. V tomto příkladu byste k opravě chyby odkazovat na objekt , který obsahuje definiciS2::f.Když v oborech názvů použijete s friend funkce, musíte před odkazem na tuto funkci znovu deklaraci schůdné funkce, jinak dojde k chybě, 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 } }Pokud chcete 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 jazyka C++ neumožňuje explicitní specializaci ve třídě. Přestože kompilátor jazyka Microsoft C++ umožňuje v některých případech, v případech, jako je následující příklad, je nyní vygenerována chyba, protože kompilátor nepovažuje druhou funkci za specializaci první z nich.
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 jednoznačně rozjednoznačit a nyní 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ídá standardu ISO C++11, následující kód by se zkompiloval a způsobil, že se
xpřekládá na typint:auto x = {0}; int y = x;Tento kód se teď překládá na typ a způsobí chybu na dalším řádku, který se pokusí
xstd::initializer_list<int>přiřadit k typuxint. (Ve výchozím nastavení neexistuje žádný převod.) Pokud chcete tento kód opravit, použijteintk nahrazeníauto:int x = {0}; int y = x;Inicializace agregace už není povolená, pokud typ hodnoty na pravé straně neodpovídá typu inicializované hodnoty na levé straně a dojde k chybě, protože ISO C++11 Standard vyžaduje jednotnou inicializaci, aby fungovala bez zužování převodů. Pokud byl dříve dostupný zužující převod, místo chyby by se vystavili upozornění kompilátoru (ú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 je v kompilátoru jazyka C++ v Visual Studio 2012 a Visual Studio 2013:
enum class E1 { a }; enum class E2 { b }; int main() { typedef E2 E1; E1::b; }V Visual Studio 2012 se
E1výraz inE1::bpřehodí do v::E1globálním oboru. Ve Visual Studio 2013 seE1výraz veE1::bvýrazu překládá natypedef E2definici vmain()souboru a má typ::E2.Rozložení objektu se změnilo. Na platformě x 64 se může v porovnání z předchozími verzemi změnit rozložení objektů třídy. Pokud má funkci, ale nemá základní třídu, která má funkci, vloží objektový model kompilátoru ukazatel do tabulky funkcí za rozložení
virtualvirtualvirtualdatového členu. To znamená, že rozložení nemusí být ve všech případech optimální. V předchozích verzích by se optimalizace pro x64 pokusila vylepšit rozložení za vás, ale protože ve složitých situacích s kódem selhala správně, byla odebrána v 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; };V Visual Studio 2013 výsledek na x64 je 48, ale v předchozích verzích se
sizeof(S2)vyhodnotí jako 32. Aby se to v kompilátoru C++ pro x64 Visual Studio 2013 32, 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 v kódu najít místa, která by se předchozí verze pokusila optimalizovat, použijte kompilátor z této verze společně s možností kompilátoru a zapněte upozornění
/W3C4370. Například:#pragma warning(default:4370) __declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };Před Visual Studio 2013 tento kód zobrazí tuto zprávu: "warning C4370: 'S2': layout of class has changed from a previous version of the compiler due to better packing".
Kompilátor x86 má stejný problém s neoptimálním 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 je
sizeof(S)24. Pokud ale použijete alternativní řešení uvedené pro x64, může se snížit na 16:struct dummy { virtual ~dummy() {} }; struct S : public dummy { virtual ~S(); int i; double d; };
Standardní knihovna
Kompilátor C++ v Visual Studio 2013 rozpozná neshody v _ITERATOR_DEBUG_LEVEL, která byla implementována v Visual Studio 2010, a neshody RuntimeLibrary. K těmto neshodám dochází v případě, že jsou smíšené možnosti kompilátoru /MT/MTd (statické /MD vydání), (statické /MDd ladění), (dynamická verze) a (dynamické ladění).
Pokud váš kód potvrdí šablony simulovaných aliasů předchozí verze, musíte ho změnit. Například místo
allocator_traits<A>::rebind_alloc<U>::otherteď musíte říciallocator_traits<A>::rebind_alloc<U>. I když už to není nutné a teď doporučujeme, abyste řekli , první typ se bude dál kompilovat, protože musí mít definici typedef s nižším poměrem, což bude stejný typ, pokud už jeratio_add<R1, R2>::typeratio_add<R1, R2>ratio<N, D>snížený.Při volání
#include <algorithm>nebo musíte použítstd::min()std::max().Pokud váš stávající kód používá simulované výčty s vymezeným oborem předchozí verze – tradiční výčty bez oborů zabalené v oborech názvů – musíte je změnit. Pokud například odkazujete na typ
std::future_status::future_status, musíte teď říctstd::future_status. Většina kódu ale není ovlivněná – například sestd::future_status::readyzkompiluje.explicit operator bool()je přísnější než operátor unspecified-bool-type().explicit operator bool()umožňuje explicitní převody na logickou hodnotu , například na , a jsou platné a "kontextové převody" testovatelné pro logickou hodnotu – například , , bez ohledu na to, co jeshared_ptr<X> spstatic_cast<bool>(sp)bool b(sp)if (sp)!spsp &&možné. Implicitní převody na bool ale zakašlete, takže nemůžete říct a zadat boolový návratový typ, nemůžeteexplicit operator bool()bool b = sp;říctreturn sp.Teď, když jsou implementované skutečné variadické šablony, _VARIADIC_MAX a související makra nemají žádný vliv. Pokud stále definujete _VARIADIC_MAX, ignoruje se. Je-li potvrzen náš nástroj maker určený k podpoře simulovaných variadic šablon jiným způsobem, je nutné změnit váš kód.
Kromě běžných klíčových slov teď hlavičky standardní knihovny C++ zakazují nahrazení maker kontextových klíčových slov přepsáním a konečným .
reference_wrapper,ref()acref()teď zakazují vazbu na dočasné objekty.<random > teď striktně vynucuje předběžné podmínky pro kompilaci.
Různé vlastnosti typu Standardní knihovna C++ mají podmínku "T má být úplný typ". I když kompilátor tuto předběžnou podmínku vynucuje striktnější, nemusí ji vynutit ve všech situacích. (Vzhledem k tomu, že porušení předběžné podmínky standardní knihovny C++ aktivují nedefinované chování, standard nezaručuje vynucení.)
Standardní knihovna C++ nepodporuje
/clr:oldSyntax.Specifikace C++11 pro měla neočekávané a nežádoucí důsledky, zejména vrací
common_type<>common_type<int, int>::typeint&&. Proto kompilátor implementuje problém 2141 navrhovaného řešení pro pracovní skupinu knihovny, který vracícommon_type<int, int="">::typeint.Vedlejším efektem této změny je, že případ identity už nefunguje ( ne vždy
common_type<T>má za následek typT). Toto chování odpovídá navrhovanému řešení, ale narušuje kód, který spoléhal na předchozí chování.Pokud vyžadujete vlastnost typu identity, nepoužívejte nestandardní typ definovaný v type_traits, protože nebude fungovat
std::identity< 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; };
Rozhraní MFC a knihovna ATL
Visual Studio 2013 pouzekód: Knihovna MFC MBCS není součástí sady Visual Studio protože kódování Unicode je tak oblíbené a použití znakové sady MBCS se výrazně snížilo. Tato změna také udržuje MFC lépe zarovnané s Windows SDK, protože mnoho ovládacích prvků a zpráv má pouze kódování Unicode. Pokud však musíte knihovnu MFC MBCS dál používat, můžete si ji stáhnout z webu Microsoft Download Center 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í instalačních komponent C++ v Visual Studio 2015 a novějších verzích).
Přístupnost pásu karet MFC se změní. Místo architektury na úrovni 1 je teď k dispozici hierarchická architektura. Staré chování můžete stále používat
CRibbonBar::EnableSingleLevelAccessibilityMode()voláním .CDatabase::GetConnectMetoda je odebrána. Pro zlepšení zabezpečení je teď připojovací řetězec uložený zašifrovaný a dešifrovaný jenom podle potřeby. Nelze ji vrátit jako prostý text. Řetězec lze získat pomocíCDatabase::Dumpmetody .CWnd::OnPowerBroadcastSignatura se změnila. Podpis tohoto popisovače zprávy se změní na LPARAM jako druhý parametr.Podpisy se mění tak, aby vyhovovaly obslužnám rutiná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ěna na (UINT, int, int) místo (WPARAM, LPARAM), aby se nové ON_WM_DISPLAYCHANGE mohlo v mapě zpráv použít nové ON_WM_DISPLAYCHANGE.CFrameWnd::OnDDEInitiatezměna na (CWnd*, UINT, UNIT) místo (WPARAM, LPARAM), aby se nové ON_WM_DDE_INITIATE mohlo použít v mapě zpráv.CFrameWnd::OnDDEExecutezměna na (CWnd*, HANDLE) místo (WPARAM, LPARAM), aby bylo možné v ON_WM_DDE_EXECUTE zpráv použít nové ON_WM_DDE_EXECUTE zpráv.CFrameWnd::OnDDETerminatebyla změněna na (CWnd*) jako parametr místo (WPARAM, LPARAM), ON_WM_DDE_TERMINATE v mapě zpráv bylo možné použít nové ON_WM_DDE_TERMINATE zpráv.CMFCMaskedEdit::OnCutzměna na žádné parametry místo (WPARAM, LPARAM), aby bylo ON_WM_CUT v mapě zpráv možné použít nové ON_WM_CUT.CMFCMaskedEdit::OnClearzměna na žádné parametry místo (WPARAM, LPARAM), aby nové ON_WM_CLEAR bylo možné použít v mapě zpráv.CMFCMaskedEdit::OnPastezměna na žádné parametry místo (WPARAM, LPARAM), aby nové ON_WM_PASTE bylo možné použít v mapě zpráv.
#ifdefDirektivy v souborech hlaviček MFC jsou odebrány. V hlavičkových souborech MFC bylo odebráno množství direktiv souvisejících s nepodporovanými Windows#ifdef(winver < 0x0501).Knihovna ATL DLL (atl120.dll) je odebrána. Knihovna ATL je nyní poskytována jako záhlaví a statická knihovna (atls.lib).
Knihovny Atlsd.lib, atlsn.lib a atlsnd.lib se odebraly. 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 trasování ATL/MFC je odebrán společně s knihovnou ATL DLL a zjednodušuje se mechanismus trasování. Konstruktor teď přebírá jeden parametr (název kategorie) a makra TRACE volají funkce
CTraceCategorygenerování sestav ladění CRT.
Visual Studio změn v roce 2012
Compiler
Možnost
/Ylkompilátoru se změnila. Ve výchozím nastavení používá kompilátor tuto možnost, což může za určitých podmínek vést k chybám LNK2011. Další informace najdete v tématu /Yl (vložení odkazu PCH do knihovny ladění).V kódu, který je zkompilován pomocí , definuje klíčové slovo třídy výčet
/clrenumC++11, nikoli výčet modulu CLR (Common Language Runtime). Chcete-li definovat výčet CLR, je nutné explicitně určit jeho přístupnost.Klíčové slovo šablony použijte k explicitnímu jednoznačnosti 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 najdete v tématu Překlad ip adres pro závislé typy.
template < typename X = "", typename = "" AY = ""> struct Container { typedef typename AY::template Rebind< X> ::Other AX; };Konstantní výraz typu float už 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 zkompilován pomocí možnosti příkazového řádku a který obsahuje ohrožení zabezpečení mimo 1, může vést k ukončení procesu za běhu, jak je znázorněno v následujícím
/GSpříkladu pseudokódu.char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminateVýchozí architektura sestavení x86 se změní na SSE2. Proto může kompilátor generovat instrukce SSE a bude používat registry XMM k provádění výpočtů s plovoucí desetinnou čárkou. Pokud se chcete vrátit k předchozímu chování, použijte příznak kompilátoru k určení architektury
/arch:IA32jako IA32.Kompilátor může vydávat upozornění upozornění kompilátoru (úroveň 4) C4703 a C4701, pokud předtím ne. Kompilátor používá silnější kontroly použití neinicializovaných místních proměnných typu ukazatele.
Pokud je zadán příznak nového linkeru, Windows 8 obvykle způsobí, že přidělení paměti vrátí
/HIGHENTROPYVA64bitovou adresu. (Před Windows 8 přidělení častěji vrátila adresy, které byly menší než 2 GB.) Tato změna může v existujícím kódu vystavit chyby zkrácení ukazatele. Ve výchozím nastavení je tento přepínač povolen. Pokud chcete toto chování zakázat, zadejte/HIGHENTROPYVA:NO.Spravovaný kompilátor (Visual Basic/C#) podporuje také
/HIGHENTROPYVApro spravovaná sestavení. V tomto případě je/HIGHENTROPYVAswitchale ve výchozím nastavení vypnutý.
IDE – integrované vývojové prostředí
- Přestože v jazyce C++/CLI Windows nevytvářejte aplikace Forms, je podporována údržba stávajících aplikací uživatelského rozhraní C++/CLI. Pokud potřebujete vytvořit aplikaci Windows Forms nebo jakoukoli jinou aplikaci uživatelského rozhraní .NET, použijte jazyk C# nebo Visual Basic. Používejte C++/CLI jenom pro účely interoperability.
Knihovna Paralelní vzory a Concurrency Runtime knihovna
Výčet SchedulerType pro UmsThreadDefault je zastaralý. Specifikace vytvoří UmsThreadDefault zastaralé upozornění a interně se mapuje zpět na ThreadScheduler .
Standardní knihovna
Po změně typu rozbíjení mezi standardy C++98/03 a C++11 se explicitní argumenty šablony pro volání ( jako v ) obvykle nezkompilují v Visual C++ v
make_pair()make_pair<int, int>(x, y)Visual Studio 2012. Řešením je vždy volat bezmake_pair()explicitních argumentů šablony – jako vmake_pair(x, y). Poskytnutí explicitních argumentů šablony porazí účel funkce. Pokud požadujete přesnou kontrolu nad výsledným typem, použijtepairmísto – jako vmake_pairpair<short, short>(int1, int2).další zásadní změna mezi standardy c++ 98/03 a c++ 11: když je implicitně převoditelné na B a b je implicitně převoditelná na c, ale není implicitně převoditelná na c, c++ 98/03 a Visual Studio 2010 s povoleným
pair<A, X>převodem (implicitně nebo explicitně) napair<C, X>. (Druhý typ, X, není zde důležité a není specifický pro první typ v páru.) kompilátor jazyka C++ v Visual Studio 2012 detekuje, že není možné implicitně převést na jazyk C a odebírá dvojici převodů z řeš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>&)volánífunc()spair<const char *, const char *>touto změnou se zkompiluje. Tato změna však přerušuje kód, který se opírá o agresivní převody párů. Takový kód může být obvykle vyřešen prováděním jedné části převodu explicitně – například předánímmake_pair(static_cast<B>(a), x)funkci, která očekávápair<C, X>.Visual Studio 2010 simulovaných šablon variadické, například
make_shared<T>(arg1, arg2, argN)– až do limitu 10 argumentů, pomocí razítka přetížení a specializace pomocí strojového stroje preprocesoru. v Visual Studio 2012 se toto omezení omezuje 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 však můžete nastavit tak, že explicitně definujete _VARIADIC_MAX jako 10, projektově v rámci.C++ 11 17.6.4.3.1 [makro. Names]/2 zakazuje nahrazení klíčových slov při zahrnutí standardních hlaviček knihoven C++ v makrech. Hlavičky nyní generují chyby kompilátoru, pokud zjišťují klíčová slova nahrazená makrem. (Definování _ALLOW_KEYWORD_MACROS umožňuje zkompilovat tento kód, ale důrazně na něj nemůžeme.) V důsledku výjimky je formulář makra
newve výchozím nastavení povolený, protože hlavičky samotném způsobem chrání pomocí#pragma push_macro("new")/#undef new/#pragma pop_macro("new"). Definování _ENFORCE_BAN_OF_MACRO_NEW přesně s tím, co jeho název implikuje.chcete-li implementovat různé optimalizace a kontroly ladění, implementace standardní knihovny jazyka C++ úmyslně oddělí binární kompatibilitu mezi verzemi Visual Studio (2005, 2008, 2010, 2012). Při použití standardní knihovny jazyka C++ zakazuje kombinování souborů objektů a statických knihoven, které jsou kompilovány pomocí různých verzí do jednoho binárního souboru (EXE nebo DLL), a zakazuje předávání objektů standardní knihovny C++ mezi binárními soubory, které jsou kompilovány pomocí různých verzí. kombinování souborů objektů a statických knihoven (pomocí standardní knihovny jazyka c++, které byly zkompilovány pomocí Visual Studio 2010 s těmi, které byly zkompilovány pomocí kompilátoru jazyka c++ v Visual Studio 2012, vygeneruje chyby linkeru o _MSC_VER neshodě, kde _MSC_VER je makro obsahující hlavní verzi kompilátoru (1700 pro Visual C++ v Visual Studio 2012). tato kontrola nedokáže detekovat kombinování knihoven DLL a nemůže rozpoznat smíchání, která zahrnuje Visual Studio 2008 nebo starší.
kromě zjištění _ITERATOR_DEBUG_LEVEL neshody, které byly implementovány v Visual Studio 2010, kompilátor C++ v Visual Studio 2012 detekuje neshody běhové knihovny. K těmto neshodě dojde, pokud jsou možnosti kompilátoru
/MT(statická verze),/MTd(statický ladicí program),/MD(dynamická verze) a/MDd(dynamický ladění) smíšené.operator<(),operator>(),operator<=()aoperator>=()byly dříve k dispozici prostd::unordered_mapstdext::hash_mapřady a kontejnery, i když jejich implementace nejsou užitečné. tyto nestandardní operátory byly ze Visual C++ v Visual Studio 2012 odebrány. Kromě toho byla rozšířená implementaceoperator==()aoperator!=()prostd::unordered_maprodinu rozšířena tak, aby krylastdext::hash_maprodinu. (Doporučujeme, abyste se vyhnuli použitístdext::hash_mapřady v novém kódu.)c++ 11 22.4.1.4 [locale. codecvt] určuje, že
codecvt::length()acodecvt::do_length()by měly mít parametry, které by měly být s modifikátoremstateT&, ale Visual Studio 2010 trvaloconst stateT&. kompilátor jazyka C++ v Visual Studio 2012 přebírástateT&podle zmocnění standard. Tento rozdíl je důležitý pro každého, kdo se pokouší přepsat virtuální funkcido_length().
CRT
Halda jazyka C runtime (CRT), která se používá pro New a hodnotu (), již není soukromá. CRT nyní používá haldu procesu. To znamená, že halda není zničena při uvolnění knihovny DLL, takže knihovny DLL, které jsou staticky propojeny s CRT, musí zajistit, aby paměť, která je přidělena kódem knihovny DLL, byla vyčištěna před uvolněním.
iscsymf()Funkce uplatňuje záporné hodnoty.threadlocaleinfostructStruktura se změnila tak, aby odpovídala změnám funkcí národního prostředí.Funkce CRT, které mají odpovídající vnitřní prvky jako
memxxx(),strxxx()jsou odebrány z intrin. h. Pokud jste zahrnuli intrin. h jenom pro tyto funkce, musíte teď zahrnout odpovídající hlavičky CRT.
Rozhraní MFC a knihovna ATL
Odebrala se podpora fúze (afxcomctl32. h); Proto byly odebrány všechny metody, které jsou definovány v < afxcomctl32. h > . Soubory hlaviček < afxcomctl32. h > a < afxcomctl32. inl byly > odstraněny.
Byl změněn název
CDockablePane::RemoveFromDefaultPaneDividiernaCDockablePane::RemoveFromDefaultPaneDivider.Změnil signaturu
CFileDialog::SetDefExtna použití LPCTSTR; proto jsou sestavení Unicode ovlivněná.Byly odebrány zastaralé kategorie trasování knihovny ATL.
Signatura změnila,
CBasePane::MoveWindowaby se vybralaconst CRect.Změnili jste podpis
CMFCEditBrowseCtrl::EnableBrowseButton.Byly odebrány vlastnosti
m_fntTabsam_fntTabsBoldze třídyCMFCBaseTabCtrl.Byl přidán parametr do
CMFCRibbonStatusBarPanekonstruktorů. (Jedná se o výchozí parametr, a proto se nejedná o derozdělení do zdrojového kódu.)Do konstruktoru byl přidán parametr
CMFCRibbonCommandsListBox. (Jedná se o výchozí parametr, a proto se nejedná o derozdělení do zdrojového kódu.)AFXTrackMouseRozhraní API (a související procedura časovače) se odebralo.TrackMouseEventMísto toho použijte rozhraní Win32 API.Do konstruktoru byl přidán parametr
CFolderPickerDialog. (Jedná se o výchozí parametr, a proto se nejedná o derozdělení do zdrojového kódu.)CFileStatuszměnila se velikost struktury:m_attributečlen se změnil z bajtů na DWORD (aby odpovídal hodnotě, která je vrácena zGetFileAttributes).CRichEditCtrlaCRichEditViewpoužijte MSFTEDIT_CLASS (richedit 4,1 Control) místo RICHEDIT_CLASS (richedit 3,0 Control) v sestaveních Unicode.odebrat
AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground, protože je vždycky TRUE v Windows Vista, Windows 7 a Windows 8.odebrat
AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable, protože je vždycky TRUE v Windows Vista, Windows 7 a Windows 8.Odebráno
AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea. rozhraní API Windows volejte přímo v Windows Vista, Windows 7 a Windows 8.Odebráno
AFX_GLOBAL_DATA::DwmDefWindowProc. rozhraní API Windows volejte přímo v Windows Vista, Windows 7 a Windows 8.Přejmenováno na
AFX_GLOBAL_DATA::DwmIsCompositionEnabledIsDwmCompositionEnabled, aby se vyloučila kolize názvů.Změněné identifikátory pro určitý počet interních časovačů MFC a přesunuly definice na AFXRES. h (AFX_TIMER_ID_ *).
Změnila se signatura
OnExitSizeMovemetody, která má souhlasit s ON_WM_EXITSIZEMOVEm makrem:CFrameWndExCMDIFrameWndExCPaneFrameWnd
Byl změněn název a signatura,
OnDWMCompositionChangedkterá má souhlasit s ON_WM_DWMCOMPOSITIONCHANGEDm makrem:CFrameWndExCMDIFrameWndExCPaneFrameWnd
Změnila se signatura
OnMouseLeavemetody, která má souhlasit s ON_WM_MOUSELEAVEm makrem:CMFCCaptionBarCMFCColorBarCMFCHeaderCtrlCMFCProperySheetListBoxCMFCRibbonBarCMFCRibbonPanelMenuBarCMFCRibbonRichEditCtrlCMFCSpinButtonCtrlCMFCToolBarReplaceThisTextCMFCToolBarComboBoxEditCMFCToolBarEditCtrlCMFCAutoHideBar
Změnila se signatura,
OnPowerBroadcastkterá má souhlasit s ON_WM_POWERBROADCASTm makrem:CFrameWndExCMDIFrameWndEx
Změnila se signatura,
OnStyleChangedkterá má souhlasit s ON_WM_STYLECHANGEDm makrem:CMFCListCtrlCMFCStatusBar
Byla přejmenována interní metoda
FontFamalyProcFontsnaFontFamilyProcFonts.Bylo odebráno množství globálních statických
CStringobjektů, které eliminují nevracení paměti v některých situacích (nahrazeno #defines), a následující proměnné členů třídy:CKeyBoardManager::m_strDelimiterCMFCPropertyGridProperty::m_strFormatCharCMFCPropertyGridProperty::m_strFormatShortCMFCPropertyGridProperty::m_strFormatLongCMFCPropertyGridProperty::m_strFormatUShortCMFCPropertyGridProperty::m_strFormatULongCMFCPropertyGridProperty::m_strFormatFloatCMFCPropertyGridProperty::m_strFormatDoubleCMFCToolBarImages::m_strPngResTypeCMFCPropertyGridProperty::m_strFormat
Změnili jste podpis
CKeyboardManager::ShowAllAcceleratorsa odebrali jste parametr oddělovače akcelerátoru.Přidáno
CPropertyPage::GetParentSheet, a veCPropertyPagetřídě, zavolejte místo toho,GetParentabyste získali správné okno nadřazeného okna, které může být nadřazené nebo nejvyšším oknemCPropertyPage. Je možné, že budete muset změnit kód na voláníGetParentSheetmístoGetParent.Opravené nevyrovnané #pragma upozornění (push) v ATLBASE. H, což způsobilo nesprávné zakázání upozornění Tato upozornění jsou teď po ATLBASE povolená správně. H byla analyzována.
Přesunuly se metody související s D2D z AFX_GLOBAL_DATA do _AFX_D2D_STATE:
GetDirectD2dFactoryGetWriteFactoryGetWICFactoryInitD2DReleaseD2DRefsIsD2DInitializedD2D1MakeRotateMatrixMísto volání, například
afxGlobalData.IsD2DInitialized, volejteAfxGetD2DState->IsD2DInitialized.
Odebrala se zastaralá knihovna ATL *. Soubory CPP ze složky \atlmfc\include\
afxGlobalDataPro splnění požadavků byla na vyžádání přesunuta inicializace na vyžádání místo v čase inicializace CRTDLLMain.Do třídy se přidala
RemoveButtonByIndexMetodaCMFCOutlookBarPane.Opraveno
CMFCCmdUsageCount::IsFreqeuntlyUsedCmdnaIsFrequentlyUsedCmd.Byla opravena několik instancí aplikace
RestoreOriginalstatedoRestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).Nepoužívané metody se odebraly z
CDockablePane:SetCaptionStyle,IsDrawCaption,IsHideDisabledButtons,GetRecentSiblingPaneInfoaCanAdjustLayout.Byly odebrány
CDockablePanestatické členské proměnném_bCaptionTextam_bHideDisabledButtons.DeleteStringDo se přidala metoda overrideCMFCFontComboBox.Nepoužívané metody se odebraly z
CPane:GetMinLengthaIsLastPaneOnLastRow.Přejmenování
CPane::GetDockSiteRow(CDockingPanesRow *)naCPane::SetDockSiteRow.
Visual Studio 2010 přerušující změny
Compiler
autoKlíčové slovo 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ěná.Nové
static_assertklíčové slovo je zavedeno, což způsobí konflikt názvů, pokud v kódu již existuje identifikátor s tímto názvem.Podpora pro nový zápis lambda vylučuje podporu pro kódování identifikátoru GUID bez uvozovek v atributu UUID IDL.
.NET Framework 4 zavádí koncept poškozených výjimek stavu, což jsou výjimky, které ponechávají proces v neopravitelném poškozeném stavu. Ve výchozím nastavení nemůžete zachytit poškozenou výjimku stavu, a to ani pomocí možnosti kompilátoru/EHa, která zachycuje všechny ostatní výjimky. Chcete-li explicitně zachytit výjimku poškozeného stavu, použijte příkazy __try-__except. Nebo použijte atribut [HandledProcessCorruptedStateExceptions], aby funkce mohla zachytit poškozené výjimky stavu. Tato změna ovlivňuje hlavně systémové programátory, kteří by museli zachytit výjimku poškozeného stavu. Osm výjimek je 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ýjimce najdete v makru GetExceptionCode.
Upravená možnost kompilátoru chrání před přetečením vyrovnávací paměti
/GSkomplexnější než v dřívějších verzích. Tato verze může do zásobníku vložit další kontroly zabezpečení, které můžou snížit výkon. Pomocí klíčového__declspec(safebuffers)slova new můžete kompilátoru instruovat, aby nezadá kontroly zabezpečení pro konkrétní funkci.Pokud kompilujete s možnostmi kompilátoru (Optimalizace celého programu) i (kompilace modulu Common Language Runtime), bude tato možnost
/GL/clr/GLignorována. Tato změna byla provedena, protože kombinace možností kompilátoru poskytovala jen malé výhody. V důsledku této změny se zlepší výkon sestavení.Ve výchozím nastavení je podpora trigrafů ve Visual Studio 2010 zakázaná. K povolení
/Zc:trigraphspodpory trigrafů použijte možnost kompilátoru. 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 znakem interpunkce. Kompilátor například nahradí??=trigraf znakem #. Ve zdrojových souborech jazyka C použijte trigrafy, které používají znakovou sadu, která neobsahuje vhodné grafické znázornění některých interpunkčních znaků.Linker už nepodporuje optimalizaci pro Windows 98. Možnost
/OPT(Optimalizace) vyprodukuje chybu při kompilaci, pokud zadáte/OPT:WIN98nebo/OPT:NOWIN98.Změnily se výchozí možnosti kompilátoru, které jsou určené vlastnostmi systému sestavení RuntimeLibrary a DebugInformationFormat. Ve výchozím nastavení jsou tyto vlastnosti sestavení zadány v projektech, které jsou vytvořeny Visual C++ verze 7.0 až 10.0. Pokud migrujete projekt, který byl vytvořen Visual C++ 6.0, zvažte, jestli pro tyto vlastnosti zadat hodnotu.
V Visual Studio 2010, RuntimeLibrary = MultiThreaded ( ) a
/MDDebugInformationFormat = ProgramDatabase (/Zi). Ve Visual C++ 9.0, RuntimeLibrary = MultiThreaded ( ) a/MTDebugInformationFormat = Disabled.
CLR
- Kompilátory Microsoft C# a Visual Basic mohou nyní vytvořit žádné primární sestavení vzájemné spolupráce (no-). Sestavení no-PO může používat typy modelu COM bez nasazení příslušného primárního sestavení vzájemné spolupráce (INTEROP). Pokud využíváte sestavení bez FUNKCE vytvořená v jazyce Visual C# nebo Visual Basic, musíte odkazovat na sestavení v příkazu pro kompilaci, než budete odkazovat na jakékoli sestavení no-, které knihovnu používá.
Visual Studio projektů a MSBuild C++
Visual Studio projekty C++ jsou teď založené na MSBuild nástroje. V důsledku toho soubory projektu používají nový formát souboru XML a příponu souboru .vcxproj. Visual Studio 2010 automaticky převede soubory projektu ze starších verzí Visual Studio do nového formátu souboru. Existující projekt je ovlivněný, pokud závisí na předchozím nástroji sestavení, příponě VCBUILD.exe souboru projektu .vcproj.
V dřívějších verzích Visual C++ pozdější vyhodnocení seznamu vlastností. Nadřazený seznam vlastností může například importovat podřízený seznam vlastností a nadřazený seznam může definovat další proměnné pomocí proměnné definované v podřízeném seznamu. Pozdní vyhodnocení umožnilo nadřazenému objektu používat podřízené proměnné ještě před importem podřízeného seznamu vlastností. V Visual Studio 2010 nelze proměnnou seznamu projektů použít před tím, než ji definujete, protože MSBuild podporuje pouze počáteční vyhodnocení.
IDE – integrované vývojové prostředí
Dialogové okno ukončení aplikace už nekončí aplikací. Když funkce or v předchozích verzích zavřela maloobchodní sestavení aplikace, zobrazí knihovna C Run-Time v okně nebo dialogovém okně konzoly zprávu o ukončení
abort()terminate()aplikace. Zpráva částečně uvedla: "Tato aplikace požádala modul runtime, aby ji ukončil neobvyklým způsobem. Další informace získáte od týmu podpory aplikace. Zpráva o ukončení aplikace byla redundantní, protože Windows následně zobrazena aktuální obslužná rutina ukončení, což bylo obvykle dialogové okno Zasílání zpráv o chybách systému Windows (Dr. Watson) nebo ladicí program Visual Studio ukončení. Od Visual Studio 2010 se v knihovně C Run-Time nezobrazí zpráva. Modul runtime navíc brání ukončení aplikace před zahájením ladicího programu. Jedná se o změnu způsobovací, pouze pokud závisíte na předchozím chování zprávy o ukončení aplikace.Konkrétně pro Visual Studio 2010 nefunguje Technologie IntelliSense 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í ani překládá typy na plně kvalifikované názvy.
Knihovny
Třída SafeInt je součástí Visual C++ a už není součástí samostatného stahování. Jedná se o změnu způsobnou přerušení pouze v případě, že jste vyvinuli třídu, která má také název "SafeInt".
Model nasazení knihoven už pomocí manifestů nenajde konkrétní verzi dynamické knihovny. Místo toho název každé dynamické knihovny obsahuje její číslo verze a tento název použijete k vyhledání knihovny.
V předchozích verzích Visual Studio můžete znovu sestavit knihovny běhového času. Visual Studio 2010 už nepodporuje vytváření vlastních kopií souborů knihovny běhových knihoven jazyka C.
Standardní knihovna
<Hlavička > iterátoru už není automaticky zahrnuta mnoha dalšími soubory hlaviček. Místo toho tuto hlavičku explicitně zahrpiš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í, příponě VCBUILD.exe souboru projektu .vcproj.iterator.
V <> hlavičce algoritmu jsou odebrány checked_* a unchecked_*. A v < hlavičce >> iterátoru je třída odebrána a
checked_iteratortřída bylaunchecked_array_iteratorpřidána.Konstruktor
CComPtr::CComPtr(int)je odebrán. Tento konstruktor umožnil vytvoření objektu z makra NULL, ale byl nepotřebný a byl povolen nesmyslné konstrukce zCComPtrnenulových celých čísel.Objekt může být vytvořen z hodnoty NULL, která je definována jako 0, ale selže, pokud je vytvořen z jiného celého čísla než
CComPtrliterálu 0. Místo toho použijtenullptr.Byly
ctypeodebrány následující členské funkce:ctype::_Do_narrow_s,ctype::_Do_widen_s, ,ctype::_narrow_sctype::_widen_s. Pokud aplikace používá jednu z těchto členských funkcí, musíte ji nahradit odpovídající nezabezpečenější verzí:ctype::do_narrow,ctype::do_widen, ,ctype::narrowctype::widen.
Knihovny CRT, MFC a ATL
Byla odebrána podpora pro uživatele při sestavování 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 pro tyto knihovny. A dokument, který popisuje MSBuild, které Microsoft používá k sestavení těchto knihoven, bude pravděpodobně zveřejněn na Visual C++ blogu týmu.
Byla odebrána podpora MFC pro IA64. Podpora CRT a ATL v IA64 je však stále k dispozici.
V souborech definice modulu MFC (.def) se už nebudou opakovaně používat ordinaly. Tato změna znamená, že se rozdíly mezi dílčími verzemi nebudou lišit. Vylepší se binární kompatibilita aktualizací Service Pack a rychlé opravy technických verzí.
Do třídy byla přidána nová virtuální
CDocTemplatefunkce. Tato nová virtuální funkce je CDocTemplate – třída. Předchozí verze nástrojeOpenDocumentFileměla dva parametry. Nová verze má tři parametry. Pro podporu správce restartování musí každá třída odvozená z implementovatCDocTemplateverzi, která má tři parametry. Nový parametr jebAddToMRU.
Makra a proměnné prostředí
- Proměnná prostředí __MSVCRT_HEAP_SELECT už není podporovaná. Tato proměnná prostředí je odebrána a neexistuje žádná náhrada.
Microsoft Macro Assembler – referenční dokumentace
- Z kompilátoru Microsoft Macro Assembler Reference bylo odebráno několik direktiv. Odebrané direktivy
.186jsou , , , , , a.286.286P.287.8086.8087.NO87.
Visual Studio 2008 Breaking Changes
Compiler
Podporované Windows 95, Windows 98, Windows ME a systém Windows NT se už nepodporují. Tyto operační systémy byly ze seznamu cílových platforem odebrány.
Kompilátor už nepodporuje více atributů, které byly přímo přidruženy k ATL Serveru. Následující atributy se už nepodporují:
perf_counter
perf_object
Perfmon
request_handler
soap_handler
soap_header
soap_method
tag_name
Visual Studio projektů C++
Při upgradu projektů z předchozích verzí Visual Studio může být třeba upravit makra WINVER a _WIN32_WINNT tak, aby byla větší než nebo rovna 0x0500.
Počínaje Visual Studio 2008 nemá průvodce novým projektem možnost vytvořit projekt C++ SQL Server projektu. SQL Server projekty vytvořené pomocí starší verze nástroje Visual Studio budou i nadále zkompilovány a fungovat správně.
odebral se soubor hlaviček rozhraní API Windows Winable. h. Místo toho použijte Winuser. h.
knihovna rozhraní API Windows Rpcndr. lib byla odebrána. Místo toho připojte pomocí rpcrt4. lib.
CRT
byla odebrána podpora 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 rozhraní Windows API
GetVersionneboGetVersionExmí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í sady SSE 4,1. Další informace najdete v tématu _fpieee_flt_fpieee_flt.
knihovny C Run-Time dodávané s Visual Studio již nejsou závislé na msvcrt.dll systémových knihoven DLL.
Standardní knihovna
byla odebrána podpora 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 Visual Studio 2010) bude aplikace nyní vyhodnotit, když se iterátor pokusí zvýšit nebo snížit počet po hranicích podkladového kontejneru.
Členská proměnná c třídy zásobníku je teď deklarovaná jako chráněná. Dříve byla tato proměnná členů deklarována jako veřejná.
Chování
money_get::do_getse změnilo. Dříve při analýze peněžních částek s více číslicemi zlomky, než je metoda volána profrac_digits, sedo_getpoužily k jejich využití. Nynído_getzastaví analýzu po obnově maximálněfrac_digitsznaků.
ATL
Knihovnu ATL nelze sestavit bez závislosti na CRT. v dřívějších verzích Visual Studio lze pomocí #define ATL_MIN_CRT vytvořit projekt knihovny ATL, který je na CRT minimální. v Visual Studio 2008 jsou všechny projekty ATL na CRT závislé, bez ohledu na to, zda je definována ATL_MIN_CRT.
Základ kódu serveru ATL byl vydán jako sdílený zdrojový projekt na webu CodePlex a není nainstalován jako součást Visual Studio. Třídy kódování a dekódování dat z atlenc. h a funkce nástrojů a třídy z atlutil. h a atlpath. h jsou zachované a teď jsou součástí knihovny ATL. Několik souborů přidružených k serveru ATL již nejsou součástí Visual Studio.
Některé funkce již nejsou zahrnuty v knihovně DLL. Pořád se nacházejí v knihovně importů. Nebude to mít vliv na kód, který funkce používá staticky. Bude mít vliv pouze na kód, který tyto funkce používá dynamicky.
Makra PROP_ENTRY a PROP_ENTRY_EX jsou zastaralá a v případech zabezpečení nahrazena makry PROP_ENTRY_TYPE a PROP_ENTRY_TYPE_EX.
Sdílené třídy ATL/MFC
Knihovnu ATL nelze sestavit bez závislosti na CRT. v dřívějších verzích Visual Studio můžete použít
#define ATL_MIN_CRTk minimálnímu ovlivňování projektu knihovny ATL na CRT. v Visual Studio 2008 jsou všechny projekty ATL na CRT závislé, bez ohledu na to, zda je definována ATL_MIN_CRT.Základ kódu serveru ATL byl vydán jako sdílený zdrojový projekt na webu CodePlex a není nainstalován jako součást Visual Studio. Třídy kódování a dekódování dat z atlenc. h a funkce nástrojů a třídy z atlutil. h a atlpath. h jsou zachované a teď jsou součástí knihovny ATL. Několik souborů přidružených k serveru ATL již nejsou součástí Visual Studio.
Některé funkce již nejsou zahrnuty v knihovně DLL. Pořád se nacházejí v knihovně importů. Nebude to mít vliv na kód, který funkce používá staticky. Bude mít vliv pouze na kód, který tyto funkce používá dynamicky.
MFC
CTimeTřída:CTimeTřída teď přijímá data začínající z 1/1/1900 0001 namísto 1/1/1970 0001pořadí ovládacích prvků v dialogových oknech knihovny mfc: správné pořadí tabulátoru více ovládacích prvků v dialogovém okně knihovny mfc je narušeno, je-li ovládací prvek mfc technologie ActiveX vložen do pořadí prvků. Tato změna opravuje tento problém.
například vytvořte dialog knihovny MFC s ovládacím prvkem technologie ActiveX a několika ovládacími prvky pro úpravy. umístěte ovládací prvek technologie ActiveX uprostřed pořadí ovládacích prvků pro úpravy. spusťte aplikaci, klikněte na ovládací prvek pro úpravy, jehož pořadí karet je po technologie ActiveX ovládací prvek, a pak na tab. před touto změnou se fokus přistoupí k ovládacímu prvku pro úpravy, který následuje po technologie ActiveX ovládacím prvku místo dalšího ovládacího prvku pro úpravu v pořadí ovládacích prvků.
CFileDialogtřída: vlastní šablony proCFileDialogtřídu nelze automaticky přenést do Windows Vista. jsou stále použitelné, ale nebudou mít další funkce ani vzhled dialogů ve stylu Windows Vista.CWndTřída aCFrameWndTřída:CWnd::GetMenuBarInfometoda byla odebrána.CFrameWnd::GetMenuBarInfoMetoda je nyní nevirtuální (non-Virtual) metoda. další informace naleznete v tématu funkce GetMenuBarInfo v Windows SDK.Podpora MFC ISAPI: knihovna MFC již nepodporuje vytváření aplikací s rozhraním ISAPI (Internet Server Application Programming Interface). Pokud chcete sestavit aplikaci ISAPI, zavolejte rozšíření ISAPI přímo.
Zastaralá rozhraní API ANSI: verze ANSI několika metod MFC jsou zastaralé. Ve svých budoucích aplikacích použijte verze Unicode těchto metod. další informace najdete v tématu požadavky na sestavení pro běžné ovládací prvky systému Windows Vista.
Visual Studio 2005 přerušující změny
CRT
Mnoho funkcí se už nepoužívá. Viz zastaralé funkce CRT.
Mnoho funkcí nyní ověřuje jejich parametry a zastavuje provádění, pokud byly zadány 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 vracet kód chyby. Viz ověření parametru.
hodnota popisovače souboru – 2 se nyní používá k označení, že
stdoutnenístderrk dispozici pro výstup, například v aplikaci Windows, která nemá žádné okno konzoly. Použila se předchozí hodnota-1. Další informace najdete v tématu _fileno.Byly odebrány knihovny CRT s jedním vláknem (LIBC. lib a LIBCD. lib). Používejte vícevláknové knihovny CRT.
/MLPříznak kompilátoru již není podporován. Neuzamykání verzí některých funkcí byly přidány v případech, kdy rozdíl výkonu mezi vícevláknovým kódem a kódem s jedním vláknem je potenciálně významný.Bylo odebráno přetížení metody POW, Double POW (int, int), aby bylo lépe v souladu se standardem.
Specifikátor formátu% n již není ve výchozím nastavení podporován v žádné printf rodině funkcí, protože je podstatou nezabezpečený. Pokud dojde k% n, výchozí chování je vyvolat neplatnou obslužnou rutinu parametru. Pokud chcete povolit podporu% n, použijte
_set_printf_count_output(viz také_get_printf_count_output).sprintfnyní vytiskne záporné znaménko se znaménkem nula.swprintfbyl změněn tak, aby odpovídal standardu; nyní vyžaduje parametr velikosti. Tvarswprintfbez parametru size se už nepoužívá._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, jak řešit chyby zabezpečení.time_tje teď 64 hodnota (Pokud není definovaná _USE_32BIT_TIME_T)._spawn_wspawnFunkce Functions teď opustíerrnonezměněnou úspěšnost, jak je určeno standardem C.RTC teď ve výchozím nastavení používá velké znaky.
Funkce podpory řídicího slova s plovoucí desetinnou čárkou jsou pro aplikace zkompilované pomocí
/CLRnebo zastaralé/CLR:PURE. Zasažené funkce jsou_clear87,_clearfp,_control87,_controlfp,_fpreset,_status87,_statusfp. Upozorně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 nyní vracejí ukazatele const. Staré chování, které neconst, 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 propojování s setargv. obj nebo wsetargv. obj již není možné potlačit rozšíření zástupného znaku na příkazovém řádku jeho uzavřením do dvojitých uvozovek. Další informace najdete v tématu rozšíření argumentů zástupného znaku.
Standardní knihovna (2005)
Třída výjimky (umístěná v < hlavičce výjimky > ) byla přesunuta do
stdoboru názvů. V předchozích verzích byla tato třída v globálním oboru názvů. Chcete-li vyřešit všechny chyby, které signalizují, že třídu výjimky nelze nalézt, přidejte do kódu následující příkaz using:using namespace std;Při volání bude
valarray::resize()obsahvalarrayztracen a bude nahrazen výchozími hodnotami.resize()Metoda je určena k opětovné inicializacivalarrayspíše než k dynamickému zvětšení jako vektoru.Vyladit iterátory: aplikace sestavené pomocí ladicí verze knihovny C-Runtime, které používají iterátory nesprávně, mohou začít zobrazit výrazy Assert za běhu. chcete-li zakázat tyto kontrolní výrazy, je nutné definovat _HAS_ITERATOR_DEBUGGING (nahrazeno _ITERATOR_DEBUG_LEVEL po Visual Studio 2010) na hodnotu 0. Další informace najdete v tématu Podpora ladění iterátoru .
Visual C++ přerušující změny rozhraní .NET 2003
Compiler
Pravé kulaté závorky se teď vyžadují pro definovanou direktivu preprocesoru (c2004).
Explicitní specializace již nenaleznou parametry šablony z primární šablony (Chyba kompilátoru C2146).
K chráněnému členu (n) lze přistupovat pouze prostřednictvím členské funkce třídy (B), která dědí z třídy (A), z níž je (n) členem (Chyba kompilátoru C2247).
Vylepšené kontroly dostupnosti v kompilátoru teď zjišťují nepřístupné základní třídy (Chyba kompilátoru C2248).
Výjimka nemůže být zachycena v případě, že destruktor nebo kopírovací konstruktor je nepřístupný (C2316).
Výchozí argumenty u ukazatelů na funkce už nejsou povolené (Chyba kompilátoru C2383).
Statický datový člen nejde inicializovat prostřednictvím odvozené třídy (Chyba kompilátoru C2477).
Inicializace
typedefnení povolená standardem a teď generuje chybu kompilátoru (typedef).boolje nyní správný typ (bool).UDC teď může vytvořit nejednoznačnost pomocí přetížených operátorů (C2666).
Další výrazy se teď považují za platné konstanty ukazatele s hodnotou null (Chyba kompilátoru C2668).
Šablona <> je nyní požadována v místech, kde by ji kompilátor dřív znamenal (<>).
Explicitní specializace členské funkce mimo třídu není platná, pokud již byla funkce explicitně specializovaná prostřednictvím specializace třídy šablony (Chyba kompilátoru C2910).
Parametry šablony bez typu s plovoucí desetinnou čárkou již nejsou povoleny (Chyba kompilátoru C2993).
Šablony třídy nejsou povoleny jako argumenty typu šablony (C3206).
Názvy funkcí Friend již nejsou zavedeny do obsahujícího oboru názvů (Chyba kompilátoru C3767).
Kompilátor již nebude v makru (C4002) přijímat nadbytečné čárky.
Objekt POD typu konstruovaný s inicializátorem formuláře () bude inicializován jako výchozí (C4345).
TypeName se nyní vyžaduje, pokud je závislý název považován za typ (Upozornění kompilátoru (úroveň 1) C4346).
Funkce, které byly nesprávně považovány za specializace šablon, již nejsou považovány za (C4347).
Statické datové členy nelze inicializovat prostřednictvím odvozené třídy (C4356).
Specializace šablony třídy musí být definovaná dřív, než se použije v návratovém typu (Upozornění kompilátoru (úroveň 3) C4686).
Kompilátor nyní hlásí nedosažitelný kód (C4702).