Historie změn Microsoft C/C++ 2003 – 2015

Tento článek popisuje všechny zásadní změny od sady Visual Studio 2015 zpět k sadě Visual Studio 2003. V tomto článku se výrazy "nové chování" nebo "teď" vztahují k sadě Visual Studio 2015 a novějším verzím. Termíny "staré chování" a "před" odkazují na Visual Studio 2013 a starší verze.

Informace o nejnovější verzi sady Visual Studio najdete v tématu Co je nového pro jazyk C++ v sadě Visual Studio a vylepšení shody jazyka C++ v sadě Visual Studio.

Poznámka:

Mezi sadou Visual Studio 2015 a Visual Studio 2017 neexistují žádné binární zásadní změny.

Když upgradujete na novou verzi sady Visual Studio, může dojít k chybám kompilace nebo modulu runtime v kódu, který se dříve zkompiloval a spustil správně. Změny v nové verzi, které způsobují takové problémy, se označují jako zásadní změny a obvykle je vyžadují úpravy ve standardu jazyka C++, podpisech funkcí nebo rozložení objektů v paměti.

Abyste se vyhnuli chybám za běhu, které jsou obtížné rozpoznat a diagnostikovat, doporučujeme nikdy staticky propojit binární soubory kompilované pomocí jiné verze kompilátoru. Když upgradujete projekt EXE nebo DLL, nezapomeňte také provést upgrade knihoven, na které odkazuje. Nepředávejte typy CRT (C Runtime) ani standardní knihovny C++ (standardní knihovna C++) mezi binárními soubory, včetně knihoven DLL, kompilovaných pomocí různých verzí kompilátoru. Další informace naleznete v tématu Potenciální chyby předávání objektů CRT přes hranice knihovny DLL.

Nepsat kód, který závisí na konkrétním rozložení objektu, který není rozhraním COM nebo objektem POD. Pokud takový kód napíšete, musíte zajistit, aby po upgradu fungoval. Další informace naleznete v tématu Přenositelnost na rozhraních ABI.

Kromě toho průběžná vylepšení shody kompilátoru můžou někdy změnit způsob, jakým kompilátor rozumí vašemu stávajícímu zdrojovému kódu. Během sestavení můžete například najít nové nebo jiné chyby nebo dokonce rozdíly v chování v kódu, který byl dříve sestaven a zdál se, že je správně spuštěný. I když tato vylepšení nejsou zásadními změnami, jako jsou ty, které jsou popsány v tomto dokumentu, možná budete muset udělat změny ve zdrojovém kódu, abyste mohli tyto problémy vyřešit:

Změny v souladu se sadou Visual Studio 2015

C Runtime Library (CRT)

Obecné změny

  • Refaktorované binární soubory

    Knihovna CRT byla přepracována do dvou různých binárních souborů: Univerzální CRT (ucrtbase), která obsahuje většinu standardních funkcí, a knihovnu modulu runtime VC (vcruntime). Knihovna vcruntime obsahuje funkce související s kompilátorem, jako je zpracování výjimek a vnitřní funkce. Pokud používáte výchozí nastavení projektu, tato změna vás neovlivní, protože linker používá nové výchozí knihovny automaticky. Pokud jste nastavili vlastnost projektu Linker na Ignorovat všechny výchozí knihovny na Ano, nebo používáte možnost /NODEFAULTLIB linkeru na příkazovém řádku, musíte aktualizovat seznam knihoven (ve vlastnosti Dodatečné závislosti), aby zahrnoval nové, refaktorované knihovny. Nahraďte starou knihovnu CRT (libcmt.lib, libcmtd.lib, msvcrt.libmsvcrtd.lib) ekvivalentními refaktorovanými knihovnami. Pro každou ze dvou refaktorovaných knihoven existují statické (.lib) a dynamické (.dll) verze, a to produkční verze (bez přípony) a ladicí verze (s příponou "d"). Dynamické verze mají knihovnu importu, se kterou propojíte. Tyto dvě refaktorované knihovny jsou univerzální CRT, konkrétně ucrtbase.dll nebo ucrtbase.lib, ucrtbased.dll nebo ucrtbased.lib, a knihovna VC runtime, libvcruntime.libvcruntimeverze.dll a libvcruntimed.libvcruntimedverze.dll. Verze v sadě Visual Studio 2015 i Visual Studio 2017 je 140. Viz funkce knihovny CRT.

<locale.h>

  • localeconv

    Funkce localeconv deklarovaná v národním prostředí.h teď funguje správně, když je povolené národní prostředí pro jednotlivá vlákna. V předchozích verzích knihovny by tato funkce vracela lconv data pro globální lokalizaci, nikoli pro lokalizaci vlákna.

    Pokud používáte národní prostředí pro jednotlivá vlákna, měli byste zkontrolovat použití localeconv. Pokud váš kód předpokládá, že lconv vrácená data jsou pro globální národní prostředí, měli byste je opravit.

<math.h>

  • Přetížení funkcí matematické knihovny jazyka C++

    V předchozích verzích jsme <math.h> definovali některé, ale ne všechny přetížení jazyka C++ pro funkce matematické knihovny. Zbytek přetížení byl v <cmath> hlavičkovém souboru. Kód, který obsahuje pouze <math.h>, může mít problémy s řešením přetížení funkce. Nyní jsou přetížení jazyka C++ odebrána z <math.h> a jsou nalezena pouze v <cmath>.

    Chcete-li vyřešit chyby, zahrňte <cmath> pro získání deklarací funkcí, které byly odebrány z <math.h>. Tyto funkce byly přesunuty:

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

    Pokud máte kód, který používá abs s typem s plovoucí desetinnou čárkou, který obsahuje pouze záhlaví <math.h>, verze s plovoucí desetinnou čárkou už nebudou k dispozici. Volání se teď vyřeší na abs(int), i když je použit argument typu plovoucí číslo, což způsobuje chybu:

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

    Oprava tohoto upozornění spočívá v nahrazení volání abs verzí s plovoucí desetinnou čárkou abs, například fabs pro argument typu double nebo fabsf pro argument typu float, nebo zahrnutím hlavičky <cmath> a pokračováním v použití abs.

  • Shoda s pohyblivou řádovou čárkou

    Byla provedena řada změn v matematické knihovně s cílem zlepšit soulad se specifikacemi IEEE-754 a C11, příloha F, s ohledem na zvláštní případy vstupů, jako jsou NaN a nekonečna. Například tiché vstupy NaN, které byly často považovány za chyby v předchozích verzích knihovny, již nejsou považovány za chyby. Viz standard IEEE 754 a příloha F standardu C11.

    Tyto změny nezpůsobí chyby v době kompilace, ale můžou způsobit, že se programy budou chovat jinak a správněji podle standardu.

  • FLT_ROUNDS

    V sadě Visual Studio 2013 se makro FLT_ROUNDS rozšířilo na konstantní výraz, což bylo nesprávné, protože režim zaokrouhlování je možné konfigurovat za běhu, například voláním fesetroundu. Makro FLT_ROUNDS je teď dynamické a správně odráží aktuální režim zaokrouhlování.

<new> a <new.h>

  • new a delete

    V předchozích verzích knihovny byly nové a odstraněné funkce operátoru definované implementací exportovány z knihovny DLL modulu runtime (například msvcr120.dll). Tyto funkce operátoru jsou nyní vždy staticky propojeny s binárními soubory, i když používáte knihovny DLL modulu runtime.

    Nejedná se o zásadní změnu nativního nebo smíšeného kódu (/clr), ale pro kód zkompilovaný jako /clr:pure, tato změna může způsobit, že se váš kód nepodaří zkompilovat. Pokud kód zkompilujete jako /clr:pure, možná budete muset kvůli této změně přidat #include <new> nebo #include <new.h> obejít chyby sestavení. Tato/clr:pure možnost je v sadě Visual Studio 2015 zastaralá a v sadě Visual Studio 2017 není podporovaná. Kód, který musí být čistý, by měl být portován do C#.

<process.h>

  • _beginthread a _beginthreadex

    Funkce _beginthread a _beginthreadex nyní obsahují odkaz na modul, ve kterém je procedura vlákna definována po dobu trvání vlákna. To pomáhá zajistit, že se moduly nevykládají, dokud vlákno neběží až do dokončení.

<stdarg.h>

  • va_start a odkazové typy

    Při kompilaci kódu jazyka C++ se nyní v době kompilace ověřuje, že předaný argument va_start není typu reference. Argumenty typu odkazu jsou zakázány standardním jazykem C++.

<stdio.h> a <conio.h>

  • Řada funkcí printf a scanf je teď definovaná interně.

    Definice všech funkcí printf a scanf byly přesunuty inline do <stdio.h>, <conio.h> a dalších CRT hlaviček. Tato zásadní změna vede k chybě linkeru (LNK2019, nevyřešený externí symbol) ve všech programech, které deklarovaly tyto funkce lokálně bez zahrnutí odpovídajících hlaviček CRT. Pokud je to možné, měli byste kód aktualizovat tak, aby zahrnoval hlavičky CRT (to znamená přidat #include <stdio.h>) a vložené funkce, ale pokud nechcete kód upravit tak, aby zahrnoval tyto soubory hlaviček, je alternativním řešením přidat legacy_stdio_definitions.lib do vstupu linkeru.

    Pokud chcete tuto knihovnu přidat do vstupu linkeru v integrovaném vývojovém prostředí, otevřete místní nabídku uzlu projektu, zvolte Vlastnosti, poté v dialogovém okně Vlastnosti projektu zvolte Linker a upravte Vstup linkeru tak, aby zahrnoval legacy_stdio_definitions.lib do seznamu odděleného středníkem.

    Pokud váš projekt odkazuje na statické knihovny, které byly zkompilovány s verzí sady Visual Studio starší než 2015, může linker hlásit nevyřešený externí symbol. Tyto chyby mohou odkazovat na vnitřní definice pro _iob, _iob_funcnebo související importy pro určité <stdio.h> funkce ve formě imp*. Společnost Microsoft doporučuje při upgradu projektu překompilovat všechny statické knihovny s nejnovější verzí kompilátoru a knihoven jazyka C++. Pokud je knihovna třetí stranou, pro kterou zdroj není k dispozici, měli byste buď požádat o aktualizovaný binární soubor od třetí strany, nebo zapouzdřit použití této knihovny do samostatné knihovny DLL, kterou kompilujete se starší verzí kompilátoru a knihoven.

    Upozornění

    Pokud propojujete s Windows SDK 8.1 nebo starší verzí, můžete narazit na tyto nevyřešené chyby externího symbolu. V takovém případě byste měli chybu vyřešit přidáním legacy_stdio_definitions.lib do vstupu linkeru, jak je popsáno výše.

    Při řešení potíží s nevyřešenými chybami symbolů můžete pomocí dumpbin.exe prozkoumat symboly definované v binárním souboru. Zkuste následující příkazový řádek zobrazit symboly definované v knihovně.

    dumpbin.exe /LINKERMEMBER somelibrary.lib
    
  • získá a _getws

    Funkce gets a _getws byly odebrány. Funkce Gets byla odebrána ze standardní knihovny jazyka C v C11, protože ji nelze bezpečně použít. Funkce _getws byla rozšířením Microsoftu, které bylo ekvivalentní funkci gets, ale pro široké řetězce. Jako alternativy k těmto funkcím zvažte použití fgetů, fgetws, gets_s a _getws_s.

  • _cgets a _cgetws

    Funkce _cgets a _cgetws byly odebrány. Jako alternativy k těmto funkcím zvažte použití _cgets_s a _cgetws_s.

  • Formátování nekonečna a NaN

    V předchozích verzích by se nekonečna a NaN naformátovaly pomocí specifických řetězců sentinelů pro MSVC.

    • Nekonečno: 1,#INF

    • Quiet NaN (tichý NaN): 1.#QNAN

    • Signální NaN: 1.#SNAN

    • Nedefinované NaN: 1.#IND

    Některé z těchto formátů můžou mít před znaménko a můžou být formátované mírně odlišně v závislosti na šířce a přesnosti pole (někdy s neobvyklými efekty by například printf("%.2f\n", INFINITY) tiskl 1,#J, protože #INF by bylo "zaokrouhleno" na dvoucifernou přesnost). C99 zavedl nové požadavky na to, jak se mají formátovat nekonečna a NaN. Implementace MSVC teď vyhovuje těmto požadavkům. Nové řetězce jsou následující:

    • Nekonečno: inf

    • Quiet NaN: nan

    • Signalizující NaN: nan(snan)

    • Neurčené NaN: nan(ind)

    Kterákoli z těchto možností může mít předponu ve formě znaménka. Pokud se použije specifikátor formátu s velkými písmeny (%F místo %f), vytisknou se řetězce velkými písmeny (INF místo inf), jak je třeba.

    Funkce scanf byly upraveny tak, aby parsovaly tyto nové řetězce, takže tyto řetězce nyní procházejí přes printf a scanf.

  • Formátování a parsování čísel s plovoucí desetinnou čárkou

    Byly zavedeny nové algoritmy analýzy a formátování s plovoucí desetinnou čárkou, aby se zlepšila správnost. Tato změna ovlivňuje řadu funkcí printf a scanf a funkcí, jako je strtod.

    Staré algoritmy formátování by vygenerovaly pouze omezený počet číslic a pak by vyplnily zbývající desetinná místa nulou. Obvykle mohly generovat řetězce, které by se vrátily zpět na původní hodnotu s plovoucí čárkou, ale nebyly ideální, pokud jste potřebovali přesnou hodnotu (nebo její nejbližší desítkové vyjádření). Nové algoritmy formátování generují tolik číslic, kolik je potřeba k reprezentaci hodnoty (nebo k vyplnění zadané přesnosti). Jako příklad zlepšení, zvažte výsledky při tisku velké mocniny dvou:

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

    Starý výstup:

    1208925819614629200000000
    

    Nový výstup:

    1208925819614629174706176
    

    Staré algoritmy analýzy by považovaly pouze 17 významných číslic ze vstupního řetězce a zbývající číslice by zahodily. Tento přístup stačí k vygenerování úzké aproximace hodnoty představované řetězcem a výsledek je obvykle velmi blízko správnému zaokrouhlení výsledku. Nová implementace považuje všechny současné číslice a vytvoří správně zaokrouhlený výsledek pro všechny vstupy (až 768 číslic). Kromě toho tyto funkce nyní respektují režim zaokrouhlování (lze ovládat pomocí fesetroundu). Toto je potenciálně změna chování, která může narušit funkčnost, protože tyto funkce mohou produkovat různé výsledky. Nové výsledky jsou vždy správnější než staré výsledky.

  • Hexadecimální parsování a parsování plovoucí čárky pro nekonečno/NaN

    Algoritmy parsování s plovoucí desetinnou čárkou nyní budou parsovat šestnáctkové řetězce s plovoucí desetinnou čárkou (například řetězce generované specifikátory formátu printf %a a %A) a všechny řetězce nekonečna a řetězce NaN generované funkcemi printf, jak je popsáno výše.

  • %A a %a nulové doplnění

    Specifikátory formátu %a a %A formátují číslo s plovoucí řádovou čárkou jako šestnáctkovou mantisu a binární exponent. V předchozích verzích by funkce printf nesprávně doplnily řetězce nulami. Například printf("%07.0a\n", 1.0) by vytiskl 00x1p+0, místo 0x01p+0. Tato chyba byla opravena.

  • Přesnost %A a %a

    Výchozí přesnost specifikátorů formátu %A a %a je 6 v předchozích verzích knihovny. Výchozí přesnost je nyní 13 pro shodu se standardem C.

    Jedná se o změnu chování za běhu ve výstupu jakékoli funkce, která používá formátovací řetězec s %A nebo %a. Ve starém chování může být výstup používající specifikátor %A "1.1A2B3Cp+111". Výstup pro stejnou hodnotu je "1.1A2B3C4D5E6F7p+111". Pokud chcete získat staré chování, můžete zadat přesnost, například %.6A. Viz specifikace přesnosti.

  • Specifikátor %F

    Specifikátor formátu nebo převodu %F je teď podporovaný. Funkčně odpovídá formátovacímu specifikátoru %f, s výjimkou toho, že nekonečna a NaN jsou formátována velkými písmeny.

    V předchozích verzích se implementace použila k analýze F a N jako modifikátorů délky. Toto chování se datovalo zpět do doby segmentovaných adresních prostorů: tyto modifikátory délky byly použity k označení dalekých a blízkých ukazatelů, v uvedeném pořadí, jako v %Fp nebo %Ns. Toto chování bylo odebráno. Pokud je %F zjištěn, je nyní považován za specifikátor formátu %F; Pokud je zjištěna hodnota %N, považuje se nyní za neplatný parametr.

  • Formátování exponentu

    Specifikátory formátu %e a %E naformátují číslo s plovoucí desetinnou čárkou jako desetinnou mantisu a exponent. Specifikátory formátu %g a %G také v některých případech formátují čísla v tomto formuláři. V předchozích verzích by CRT vždy vygeneroval řetězce s trojcifernými exponenty. Například printf("%e\n", 1.0) by se vytisklo číslo 1,000000e+000, což bylo nesprávné. Jazyk C vyžaduje, aby byl exponent reprezentován pouze jednou nebo dvěma číslicemi, budou vytištěny pouze dvě číslice.

    V aplikaci Visual Studio 2005 byl zaveden globální přepínač shody: _set_output_format. Program může tuto funkci volat s argumentem _TWO_DIGIT_EXPONENT, aby bylo možné povolit odpovídající exponentní tisk. Výchozí chování bylo změněno na režim tisku exponentů, který odpovídá standardům.

  • Ověření řetězce formátu

    V předchozích verzích by funkce printf a scanf tiše přijímaly mnoho neplatných formátových řetězců, někdy s neobvyklými efekty. Například %hlhlhld by byl považován za %d. Všechny neplatné řetězce formátu jsou nyní považovány za neplatné parametry.

  • Ověření řetězce v režimu fopen

    Ve starších verzích funkce z rodiny fopen tiše přijímaly některé neplatné řetězce režimu, jako například r+b+. Neplatné řetězce režimu jsou nyní zjišťovány a považovány za neplatné parametry.

  • režim _O_U8TEXT

    Funkce _setmode nyní správně hlásí režim pro datové proudy otevřené v režimu in_O_U8TEXT. V předchozích verzích knihovny by takové proudy hlásila jako otevřené v režimu _O_WTEXT.

    Jedná se o zásadní změnu, pokud váš kód interpretuje režim _O_WTEXT pro datové proudy, kde kódování je UTF-8. Pokud vaše aplikace nepodporuje UTF_8, zvažte přidání podpory pro toto stále častější kódování.

  • snprintf a vsnprintf

    Funkce snprintf a vsnprintf jsou teď implementované. Starší kód často poskytoval definice verzí maker těchto funkcí, protože nebyly implementovány knihovnou CRT, ale už nejsou potřeba v novějších verzích. Pokud je snprintf nebo vsnprintf definován jako makro před zahrnutím <stdio.h>, kompilace nyní selže s chybou, která označuje, kde bylo makro definováno.

    Oprava tohoto problému obvykle spočívá v odstranění všech deklarací snprintf nebo vsnprintf v uživatelském kódu.

  • Tmpnam generuje použitelné názvy souborů.

    V předchozích verzích funkce tmpnam a tmpnam_s vygenerovaly názvy souborů v kořenovém adresáři jednotky (například \sd3c.). Tyto funkce teď generují použitelné cesty k názvům souborů v dočasném adresáři.

  • Zapouzdření SOUBORU

    V předchozích verzích byl kompletní typ FILE veřejně definován v <stdio.h>, což umožňovalo uživatelskému kódu přístup k jeho vnitřní struktuře a její úpravu. Knihovna byla změněna tak, aby skrývala podrobnosti implementace. V rámci této změny je teď SOUBOR definovaný <stdio.h> neprůmyslným typem a jeho členové jsou nepřístupní mimo samotný CRT.

  • _outp a _inp

    Funkce _outp, _outpw, _outpd, _inp, _inpw a _inpd byly odebrány.

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

  • strtof a wcstof

    Funkce strtof a wcstof nepodařilo se nastavit errno na ERANGE, když hodnota nebyla reprezentovatelná jako float. Tato chyba byla specifická pro tyto dvě funkce; , strtodwcstodstrtolda wcstold funkce nebyly ovlivněny. Tento problém byl opraven a jedná se o změnu narušující běh programu.

  • Zarovnané funkce přidělení

    V předchozích verzích by zarovnané funkce přidělování (_aligned_malloc_aligned_offset_mallocatd.) bezobslužně přijímaly požadavky na blok se zarovnáním 0. Požadované zarovnání musí být mocnina dvou, což neplatí pro nulu. Požadované zarovnání 0 je nyní považováno za neplatný parametr. Tento problém je opravený a jedná se o změnu způsobující chybu za běhu.

  • Funkce haldy

    Funkce _heapadda funkce _heapset_heapused byly odebrány. Tyto funkce jsou nefunkční od doby, co byla CRT aktualizována, která začala používat haldu Windows.

  • smallheap

    Možnost smallheap propojení byla odebrána. Viz Možnosti propojení.

  • _stat

    Rodina funkcí _stat využívá CreateFile v sadě Visual Studio 2015, místo FindFirstFile jako v sadě Visual Studio 2013 a dřívějších verzích. To znamená, že _stat na cestě končící lomítkem proběhne úspěšně, pokud cesta odkazuje na adresář, na rozdíl od dříve, kdy by funkce chybovala s nastaveným parametrem errnoENOENT.

<string.h>

  • wcstok

    Podpis wcstok funkce byl změněn tak, aby odpovídal tomu, co vyžaduje standard C. Ve starších verzích knihovny byla definice této funkce:

    wchar_t* wcstok(wchar_t*, wchar_t const*)
    

    Použil interní kontext pro jednotlivá vlákna ke sledování stavu napříč voláními, jak je tomu u strtok. Funkce teď má podpis wchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**)a vyžaduje, aby volající předal kontext jako třetí argument funkci.

    Byla přidána nová _wcstok funkce se starým podpisem pro usnadnění přenosu. Při kompilaci kódu jazyka C++ existuje také vložené přetížení wcstok , které má starý podpis. Toto přetížení je označeno jako zastaralé. Ve zdrojovém kódu jazyka C můžete definovat `define_CRT_NON_CONFORMING_WCSTOK`, aby se použilo _wcstok místo wcstok.

<time.h>

  • hodiny

    V předchozích verzích byla funkce clock implementována pomocí rozhraní API GetSystemTimeAsFileTime systému Windows. Při této implementaci byla hodinová funkce citlivá na systémový čas, a proto nebyla nutně monotónní. Funkce hodin byla reimplementována z hlediska QueryPerformanceCounter a je nyní monotónní.

  • fstat a _utime

    V předchozích verzích _stat, fstat a _utime funkce zpracovávaly letní čas nesprávně. Před verzí Visual Studio 2013 všechny tyto funkce nesprávně upravily standardní čas, jako by šlo o letní čas.

    V sadě Visual Studio 2013 se problém vyřešil ve _stat skupině funkcí, ale podobné problémy v fstat řadách funkcí a _utime rodiny funkcí nebyly opraveny. Tato částečná oprava vedla k problémům kvůli nekonzistence mezi funkcemi. fstat a _utime řady funkcí byly nyní opraveny, všechny tyto funkce nyní zpracovávají letní čas správně a konzistentně.

  • asctime

    V předchozích verzích funkce asctime doplnila jednociferné dny úvodní nulou, například: Fri Jun 06 08:00:00 2014. Specifikace vyžaduje, aby tyto dny byly zarovnány úvodní mezerou, jako v Fri Jun 6 08:00:00 2014. Tento problém byl opraven.

  • strftime a wcsftime

    strftime Funkce wcsftime teď podporují specifikátory formátu %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %u a %V. Modifikátory E a O se navíc analyzují, ale ignorují.

    Specifikátor formátu %c je určen jako vytvoření "odpovídající reprezentace data a času" pro aktuální národní prostředí. V národním prostředí jazyka C musí být tato reprezentace stejná jako %a %b %e %T %Y, stejná forma, jakou vytváří asctime. V předchozích verzích specifikátor formátu %c nesprávně formátoval časy pomocí MM/DD/YY HH:MM:SS reprezentace. Tento problém byl opraven.

  • timespec a TIME_UTC

    Hlavička <time.h> teď definuje timespec typ a funkci ze standardu timespec_get C11. Kromě toho je nyní definováno makro TIME_UTC pro použití s timespec_get funkcí. Tato aktualizace představuje zásadní změnu kódu, která má konfliktní definici pro kterýkoli z těchto identifikátorů.

  • CLOCKS_PER_SEC

    Makro CLOCKS_PER_SEC se teď rozbalí na celé číslo typu clock_t, jak to vyžaduje jazyk C.

Standardní knihovna C++

Aby bylo možné povolit nové optimalizace a kontroly ladění, implementace C++ Standardní knihovny ve Visual Studiu záměrně narušuje binární kompatibilitu z jedné verze na další. Proto při použití standardní knihovny C++ nelze objektové soubory a statické knihovny, které jsou kompilovány pomocí různých verzí, směšovat v jednom binárním souboru (EXE nebo DLL) a objekty standardní knihovny C++ nelze předávat mezi binárními soubory, které jsou kompilovány pomocí různých verzí. Míchání objektů tohoto typu vyvolává chyby linkeru týkající se neshod _MSC_VER. (_MSC_VER je makro, které obsahuje hlavní verzi kompilátoru – například 1800 pro Visual Studio 2013.) Tato kontrola nedokáže rozpoznat kombinování knihoven DLL a nedokáže rozpoznat kombinování, které zahrnuje Visual Studio 2008 nebo starší.

  • Standardní knihovna C++ – zahrnutí souborů

    V hlavičkách standardní knihovny C++ byly provedeny některé změny ve struktuře zahrnutí. Hlavičky standardní knihovny jazyka C++ mohou zahrnovat jedna druhou nezpůsobem, který není specifikován. Obecně byste měli napsat kód tak, aby pečlivě zahrnoval všechny hlavičky, které potřebuje podle standardu C++, a nespoléhá na to, které hlavičky standardní knihovny C++ zahrnují další hlavičky standardní knihovny C++. Díky tomu je kód přenosný napříč verzemi a platformami. Nejméně dvě změny hlaviček v sadě Visual Studio 2015 ovlivňují uživatelský kód. Za prvé, <string> již neobsahuje <iterator>. Za druhé, <tuple> nyní deklaruje std::array bez zahrnutí všech <array>, což může přerušit kód pomocí následující kombinace konstrukcí kódu: váš kód má proměnnou s názvem "array" a máte direktivu použití "using namespace std;" a zahrnete hlavičku standardní knihovny jazyka C++ (například <functional>) zahrnující <tuple>, která nyní deklaruje std::array.

  • steady_clock

    Implementace <chrono>steady_clock se změnila tak, aby splňovala standardní požadavky jazyka C++ na stálost a monotonitu. steady_clock je nyní založen na QueryPerformanceCounter a high_resolution_clock je nyní typedef pro steady_clock. V důsledku toho je ve Visual Studio steady_clock::time_point nyní typedef na chrono::time_point<steady_clock>; to však nemusí nutně platit pro jiné implementace.

  • alokátory a konstanta 'const'

    Nyní vyžadujeme, aby porovnávání rovnosti a nerovnosti alokátorů přijímalo const argumenty na obou stranách. Pokud vaše alokátory definují tyto operátory takto,

    bool operator==(const MyAlloc& other)
    

    pak byste je měli aktualizovat a deklarovat jako členy const:

    bool operator==(const MyAlloc& other) const
    
  • const – prvky

    Standard C++ má vždy zakázané kontejnery prvků const (například vector<const T> ).set<const T> Visual Studio 2013 a starší tyto kontejnery přijali. V aktuální verzi se takové kontejnery nepodaří zkompilovat.

  • std::allocator::deallocate

    V aplikaci Visual Studio 2013 a dřívějších verzích std::allocator::deallocate(p, n) ignoroval argument předaný pro n. Standard jazyka C++ vždy vyžaduje, aby n musel být roven hodnotě předané jako první argument vyvolání allocate, které vrátilo p. V aktuální verzi se ale zkontroluje hodnota n . Kód, který předává argumenty pro n , které se liší od standardních požadavků, může při běhu dojít k chybovému ukončení.

  • hash_map a hash_set

    Nestandardní hlavičkové soubory <hash_map> a <hash_set> jsou ve Visual Studio 2015 zastaralé a budou odstraněny v budoucí verzi. Použijte <unordered_map> a <unordered_set> místo toho.

  • komparátory a operátory()

    Asociativní kontejnery (rodina <map>) nyní vyžadují, aby jejich komparátory měly operátory volání funkce s konst-volatelnými operátory. Následující kód v deklaraci srovnávací třídy se teď nepodaří zkompilovat:

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

    Pokud chcete tuto chybu vyřešit, změňte deklaraci funkce na:

    bool operator()(const X& a, const X& b) const
    
  • typové vlastnosti

    Staré názvy pro vlastnosti typu ze starší verze konceptu C++ byly odebrány. Byly změněny v C++11 a aktualizovány na hodnoty C++11 v sadě Visual Studio 2015. V následující tabulce jsou uvedeny staré a nové názvy.

    Starý název Nový název
    přidat_odkaz přidat_lvalue_reference
    má_výchozí_konstruktor (has_default_constructor) je možné vytvořit pomocí výchozího konstruktoru
    má konstruktor kopie (has_copy_constructor) je_kopírovatelná_sestrojitelnost
    has_move_constructor is_move_constructible
    has_nothrow_constructor (má konstruktér bez výjimek) is_nothrow_default_constructible
    has_nothrow_default_constructor (má výchozí konstruktor, který nevyhazuje výjimky) is_nothrow_default_constructible
    has_nothrow_copy (zajišťuje kopírování bez vyvolání výjimek) is_nothrow_copy_constructible
    In cases where translation is deemed necessary or beneficial: - má_copy_konstruktor_bez_výjimky is_nothrow_copy_constructible
    má_konstruktor_bezpříhozového_přesunu is_nothrow_move_constructible
    má_bezvýjimkový_přiřazení is_nothrow_copy_assignable
    has_nothrow_copy_assign is_nothrow_copy_assignable
    má_bezvýjimkové_přiřazení_přesunu is_nothrow_move_assignable
    má_triviální_konstruktor is_trivially_default_constructible (je triviálně výchozí libovolně vytvořitelný)
    má triviální výchozí konstruktor is_trivially_default_constructible (je triviálně výchozí libovolně vytvořitelný)
    má_triviální_kopii is_trivially_copy_constructible
    If localization is not required and it's a recognized term, it should remain unchanged. If translation is needed, consult a technical dictionary or subject matter expert. is_trivially_přesouvatelný_konstruktibilní
    má_triviální_přiřazení je_triviálně_přiřaditelné_kopírováním
    má_triviální_přiřazení_úkolu_přesunu is_trivially_move_assignable
    má triviální destruktor je_triviálně_ničitelné
  • launch::any a launch::sync politiky

    Nestandardní zásady launch::any a launch::sync byly odebrány. Místo toho pro launch::any použijte launch:async | launch:deferred. Pro launch::sync použijte launch::deferred. Viz launch Enumeration.

MFC a ATL

  • Knihovna MFC (Microsoft Foundation Classes)

    není už součástí typické instalace sady Visual Studio kvůli své velké velikosti. Pokud chcete nainstalovat prostředí MFC, zvolte možnost Vlastní instalace v instalačním programu sady Visual Studio 2015. Pokud už máte nainstalovanou sadu Visual Studio 2015, můžete prostředí MFC nainstalovat opětovným spuštěním instalace sady Visual Studio . Zvolte možnost Vlastní instalace a pak zvolte Třídy služby Microsoft Foundation. Instalační program sady Visual Studio můžete spustit z Ovládacích panelů v části Programy a funkce nebo z instalačního média.

    Distribuovatelný balíček Visual C++ stále zahrnuje i tuto knihovnu.

Concurrency Runtime

  • Výnos makra z Windows.h v konfliktu s souběžností::Context::Yield

    Modul Concurrency Runtime dříve použil #undef k nedefinaci makra Yield, aby nedocházelo ke konfliktům mezi makrem Yield definovaným ve Windows.h a concurrency::Context::Yield funkcí. Tento #undef byl odstraněn a bylo přidáno nové nekonfliktní ekvivalentní volání API concurrency::Context::YieldExecution. Pokud chcete obejít konflikty s Yield, můžete aktualizovat kód tak, aby místo toho volal funkci YieldExecution, nebo ohraničit název funkce Yield do závorek v místech volání, jak je znázorněno v následujícím příkladu:

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

Vylepšení shody kompilátoru v sadě Visual Studio 2015

Při upgradu kódu z předchozích verzí můžete také narazit na chyby kompilátoru, které jsou způsobeny vylepšeními shody v sadě Visual Studio 2015. Tato vylepšení neporušují binární kompatibilitu ze starších verzí sady Visual Studio, ale můžou způsobit chyby kompilátoru, ve kterých se předtím nevygenerovaly žádné. Další informace najdete v tématu Visual C++ What's New 2003 až 2015.

V sadě Visual Studio 2015 můžou probíhající vylepšení souladu kompilátoru někdy změnit způsob, jakým kompilátor rozumí vašemu existujícímu zdrojovému kódu. V důsledku toho můžete během sestavení narazit na nové nebo odlišné chyby nebo dokonce na odlišnosti v chování kódu, který se dříve sestavil a zdál se správně spuštěný.

Tyto rozdíly naštěstí mají malý nebo žádný vliv na většinu zdrojového kódu. Pokud jsou k vyřešení těchto rozdílů potřeba zdrojový kód nebo jiné změny, opravy jsou obvykle malé a jednoduché. Zahrnuli jsme mnoho příkladů dříve přijatelného zdrojového kódu, které možná bude potřeba změnit (před) a jejich opravy (po).

I když tyto rozdíly můžou ovlivnit zdrojový kód nebo jiné artefakty sestavení, nemají vliv na binární kompatibilitu mezi aktualizacemi verzí sady Visual Studio. Zásadní změna je vážnější a může ovlivnit binární kompatibilitu, ale tyto druhy přerušení binární kompatibility se vyskytují pouze mezi hlavními verzemi sady Visual Studio, například mezi sadou Visual Studio 2013 a sadou Visual Studio 2015. Informace o zásadních změnách, ke kterým došlo mezi sadou Visual Studio 2013 a Visual Studio 2015, najdete v tématu Změny shody sady Visual Studio 2015.

Vylepšení kompatibility v sadě Visual Studio 2015

  • /Zc:forScope- přepínač

    Možnost /Zc:forScope- kompilátoru je zastaralá a bude odebrána v budoucí verzi.

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

    Tato možnost se obvykle použila k povolení nestandardního kódu, který používá proměnné smyčky za bodem, kde by podle standardu měly být mimo rozsah. Bylo nutné pouze v případě, že jste kompilovali s /Za možností, protože bez /Zapoužití proměnné smyčky for po ukončení smyčky je vždy povoleno. Pokud vás nezajímá shoda se standardy (například pokud váš kód nemá být přenositelný do jiných kompilátorů), můžete tuto možnost vypnout /Za (nebo nastavit vlastnost Disable Language Extensions na Ne). Pokud vás zajímá psaní přenosného kódu vyhovujícího standardům, měli byste kód přepsat tak, aby odpovídal standardu přesunutím deklarace těchto proměnných do bodu mimo smyčku.

    // C2065 expected
    int main() {
        // Uncomment the following line to resolve.
        // int i;
        for (int i = 0; i < 1; i++);
        i = 20;   // i has already gone out of scope under /Za
    }
    
  • /Zg Možnost kompilátoru

    Možnost kompilátoru /Zg (Generování prototypů funkcí) už není dostupná. Tato možnost kompilátoru byla dříve zastaralá.

  • Testy jednotek s C++/CLI už nemůžete spouštět z příkazového řádku s mstest.exe. Místo toho použijte vstest.console.exe. Viz VSTest.Console.exe možnosti příkazového řádku.

  • proměnlivé klíčové slovo

    mutable Specifikátor třídy úložiště už není povolený na místech, kde se dříve zkompiloval bez chyby. Kompilátor teď zobrazí chybu C2071 (neplatná třída úložiště). Podle standardu mutable lze specifikátor použít pouze na názvy datových členů třídy a nelze jej použít u názvů deklarovaných const nebo static a nelze jej použít pro referenční členy.

    Představte si například následující kód:

    struct S
    {
        mutable int &r;
    };
    

    Předchozí verze kompilátoru to přijali, ale teď kompilátor zobrazí následující chybu:

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

    Pokud chcete chybu opravit, odeberte redundantní mutable klíčové slovo.

  • char_16_t a char32_t

    Už nemůžete používat char16_t ani char32_t jako aliasy v typedef, protože tyto typy jsou nyní považovány za předdefinované. Pro uživatele a autory knihoven bylo běžné definovat char16_t a char32_t jako aliasy uint16_t a uint32_tv uvedeném pořadí.

    #include <cstdint>
    
    typedef uint16_t char16_t; //C2628
    typedef uint32_t char32_t; //C2628
    
    int main(int argc, char* argv[])
    {
        uint16_t x = 1; uint32_t y = 2;
        char16_t a = x;
        char32_t b = y;
        return 0;
    }
    

    Chcete-li aktualizovat kód, odeberte typedef deklarace a přejmenujte všechny ostatní identifikátory, které s těmito názvy kolidují.

  • Parametry šablony bez typu

    Při zadávání explicitních argumentů šablony se teď správně kontroluje kompatibilita typů s určitým kódem, který zahrnuje parametry šablony jiného typu. Například následující kód se zkompiloval bez chyby v předchozích verzích sady Visual Studio.

    struct S1
    {
        void f(int);
        void f(int, int);
    };
    
    struct S2
    {
        template <class C, void (C::*Function)(int) const> void f() {}
    };
    
    void f()
    {
        S2 s2;
        s2.f<S1, &S1::f>();
    }
    

    Aktuální kompilátor správně zobrazí chybu, protože typ parametru šablony neodpovídá argumentu šablony (parametr je ukazatel na člen const, ale funkce f není const):

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

    Pokud chcete tuto chybu vyřešit v kódu, ujistěte se, že typ argumentu šablony, který používáte, odpovídá deklarovanému typu parametru šablony.

  • __declspec(align)

    Kompilátor už nepřijímá __declspec(align) na funkcích. Tento konstruktor byl vždy ignorován, ale nyní vytvoří chybu kompilátoru.

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

    Chcete-li tento problém vyřešit, odeberte __declspec(align) z deklarace funkce. Vzhledem k tomu, že neměl žádný vliv, odebrání nic nemění.

  • Ošetření výjimek

    Zpracování výjimek má několik změn. Za prvé, objekty výjimek musí být buď kopírovatelné nebo pohyblivé. Následující kód zkompilovaný v sadě Visual Studio 2013, ale nekompiluje se v sadě Visual Studio 2015:

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

    Problémem je, že konstruktor kopírování je soukromý, takže objekt nelze zkopírovat tak, jak se děje v normálním průběhu zpracování výjimky. Totéž platí při deklaraci explicitkonstruktoru kopírování .

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

    Chcete-li aktualizovat kód, ujistěte se, že kopírovací konstruktor vašeho objektu výjimky je public a není označen explicit.

    Zachycení výjimky podle hodnoty také vyžaduje, aby objekt výjimky byl kopírovatelný. Následující kód zkompilovaný v sadě Visual Studio 2013, ale nekompiluje se v sadě Visual Studio 2015:

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

    Tento problém můžete vyřešit změnou typu parametru catch na odkaz.

    catch (D& d)
    {
    }
    
  • Řetězcové literály následované makry

    Kompilátor teď podporuje uživatelsky definované literály. V důsledku toho se řetězcové literály následované makry bez jakýchkoli mezer interpretují jako literály definované uživatelem, což může vést k chybám nebo k neočekávaným výsledkům. Například v předchozích kompilátorech se následující kód úspěšně zkompiloval:

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

    Kompilátor interpretoval tento kód jako řetězcový literál "hello", za kterým následuje makro, které je rozvinuto na "there", a potom byly tyto dva řetězcové literály spojeny do jednoho. V sadě Visual Studio 2015 kompilátor interpretuje tuto sekvenci jako literál definovaný uživatelem, ale protože neexistuje žádná odpovídající uživatelsky definovaná literála _x , zobrazí chybu.

    error C3688: invalid literal suffix '_x'; literal operator or literal operator template 'operator ""_x' not found
    note: Did you forget a space between the string literal and the prefix of the following string literal?
    

    Chcete-li tento problém vyřešit, přidejte mezeru mezi řetězcový literál a makro.

  • Sousední řetězcové literály

    Podobně jako v předchozím případě se vzhledem ke změnám souvisejícím s parsováním řetězců vykládaly sousední řetězcové literály (ať už široké nebo úzké znakové literály) bez prázdných znaků jako jediný zřetězený řetězec v předchozích verzích Visual C++. V aplikaci Visual Studio 2015 teď musíte mezi dva řetězce přidat mezeru. Například musí být změněn následující kód:

    char * str = "abc""def";
    

    Pokud chcete tento problém vyřešit, přidejte mezi tyto dva řetězce mezeru:

    char * str = "abc" "def";
    
  • Nové umístění a odstranění

    Došlo ke změně operátoru delete s cílem uvést ho do souladu se standardem C++14. Podrobnosti o změně standardů najdete na stránce C++ Sized Deallocation. Změny přidávají formu globálního delete operátoru, který přebírá parametr velikosti. Změna způsobující chybu spočívá v tom, že pokud jste dříve používali operátor delete se stejným podpisem (aby odpovídal operátoru umístění new), zobrazí se chyba kompilátoru (C2956, ke které dochází v okamžiku, kdy se použije operátor umístění new, protože jde o pozici v kódu, kde se kompilátor pokusí identifikovat odpovídající delete operátor).

    Funkce void operator delete(void *, size_t) byla operátorem odstranění umístění, který odpovídá nové funkci void * operator new(size_t, size_t) umístění v jazyce C++11. S dealokací velikosti v C++14 je nyní tato funkce delete obvyklou funkcí dealokace (globální operátor). Standard vyžaduje, aby pokud použití nové umístění vyhledá odpovídající funkci odstranění a najde obvyklou funkci přidělení, program je špatně vytvořen.

    Předpokládejme například, že váš kód definuje jak placement new, tak placement delete:

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

    K problému dochází z důvodu shody v podpisech funkce mezi vámi definovaným operátorem placement delete a novým globálním operátorem delete. Zvažte, zda můžete pro jakýkoli operátor placement new a delete použít jiný typ než size_t. Typ size_ttypedef závisí na kompilátoru; pro unsigned int v MSVC je to typedef. Dobrým řešením je použít výčtový typ, například tento:

    enum class my_type : size_t {};
    

    Pak změňte definici placement new a delete a jej použijte jako druhý argument místo size_t. Budete také muset aktualizovat volání operatoru placement new, aby se předal nový typ (například pomocí static_cast<my_type> přetypování z celočíselné hodnoty) a přetypovat definici new a delete zpět na typ integer. Pro tento typ není nutné použít enum . Typ třídy s size_t členem by také fungoval.

    Alternativním řešením je, že můžete zcela eliminovat placement new. Pokud váš kód používá placement new pro implementaci fondu paměti, kde je argumentem umístění velikost objektu, který je přidělován nebo uvolňován, může být funkce přidělení podle velikosti vhodná k nahrazení vašeho vlastního kódu fondu paměti. Můžete se zbavit funkcí umístění a použít pouze vlastní operátor se dvěma argumenty delete místo funkcí umístění.

    Pokud nechcete kód okamžitě aktualizovat, můžete se vrátit ke starému chování pomocí možnosti /Zc:sizedDealloc-kompilátoru . Pokud použijete tuto možnost, funkce delete se dvěma argumenty neexistují a nezpůsobí konflikt s operátorem placement delete.

  • Datové členy unie

    Členové unie již nemohou mít odkazové typy. Následující kód byl úspěšně zkompilován v sadě Visual Studio 2013, ale v sadě Visual Studio 2015 dojde k chybě.

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

    Předchozí kód generuje následující chyby:

    test.cpp(67): error C2625: 'U2::i': illegal union member; type 'int &' is reference type
    test.cpp(70): error C2625: 'U3::i': illegal union member; type 'int &' is reference type
    

    Pokud chcete tento problém vyřešit, změňte odkazové typy buď na ukazatel, nebo na hodnotu. Změna typu na ukazatel vyžaduje změny v kódu, který používá sjednocovací pole. Změna kódu na hodnotu by změnila data uložená ve sjednocení, což má vliv na jiná pole, protože pole v typech sjednocení sdílejí stejnou paměť. V závislosti na velikosti hodnoty se může také změnit velikost unie.

  • Anonymní sjednocení jsou nyní více v souladu se standardem. Předchozí verze kompilátoru generovaly explicitní konstruktor a destruktor pro anonymní unie. Tyto funkce generované kompilátorem se odstraní v sadě Visual Studio 2015.

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

    Předchozí kód vygeneruje v sadě Visual Studio 2015 následující chybu:

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

    Pokud chcete tento problém vyřešit, zadejte vlastní definice konstruktoru nebo destruktoru.

    struct S
    {
        // Provide a default constructor by adding an empty function body.
        S() {}
    };
    
    union
    {
        struct
        {
            S s;
        };
    } u;
    
  • Sjednocení s anonymními strukturami

    Aby bylo možné splňovat standard, chování modulu runtime se změnilo pro členy anonymních struktur v sjednoceních. Konstruktor pro anonymní členy struktury v unii již není implicitně volán při vytvoření takové unie. Také destruktor pro anonymní členy struktury v unii se již implicitně nevolá, když unie přejde mimo rozsah. Vezměte v úvahu následující kód, ve kterém sjednocení U obsahuje anonymní strukturu, která obsahuje pojmenovanou členskou strukturu S, která má destruktor.

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

    Ve Visual Studio 2013 se při vytvoření unionu volá konstruktor pro S a při uvolnění zásobníku pro funkci f se volá destruktor pro S. V sadě Visual Studio 2015 se ale konstruktor a destruktor nevolají. Kompilátor zobrazí upozornění na tuto změnu chování.

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

    Chcete-li obnovit původní chování, dejte anonymní struktuře název. Chování modulu runtime neanonymních struktur je stejné bez ohledu na verzi kompilátoru.

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

    Případně zkuste přesunout kód konstruktoru a destruktoru do nových funkcí a zavolat tyto funkce z konstruktoru a destruktoru pro unii.

    #include <stdio.h>
    
    struct S
    {
        void Create() { printf("Creating S.\n"); }
        void Destroy() { printf("Destroying S\n"); }
    };
    union U
    {
        struct
        {
            S s;
        };
        U() { s.Create(); }
        ~U() { s.Destroy(); }
    };
    
    void f()
    {
        U u;
    }
    
    int main()
    {
        f();
    
        char s[1024];
        printf("Press any key.\n");
        gets_s(s);
        return 0;
    }
    
  • Rozlišení šablon

    Byly provedeny změny v rozlišování názvů pro šablony. V jazyce C++ může při zvažování kandidátů na rozlišení jména dojít k tomu, že jedno nebo více jmen, která jsou zvažovaná jako potenciální shody, vytvoří neplatnou instanci šablony. Tyto neplatné instance obvykle nezpůsobují chyby kompilátoru, princip označovaný jako SFINAE (selhání nahrazení není chyba).

    Pokud teď SFINAE vyžaduje, aby kompilátor vytvořil instanci specializace šablony třídy, všechny chyby, ke kterým dojde během tohoto procesu, jsou chyby kompilátoru. V předchozích verzích by kompilátor takové chyby ignoroval. Představte si například následující kód:

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

    Pokud kompilujete s aktuálním kompilátorem, zobrazí se následující chyba:

    type_traits(1110): error C2139: 'D': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_base_of'
    ..\t331.cpp(14): note: see declaration of 'D'
    ..\t331.cpp(10): note: see reference to class template instantiation 'std::is_base_of<T,U>' being compiled
    with
    [
        T=D,
        U=D
    ]
    

    Důvodem je to, že v okamžiku prvního vyvolání is_base_of třída D ještě nebyla definována.

    V tomto případě je oprava nepoužívat takové vlastnosti typu, dokud není definována třída. Pokud přesunete definice B souboru kódu a D na začátek souboru kódu, chyba se vyřeší. Pokud jsou definice v souborech hlaviček, zkontrolujte pořadí příkazů include pro soubory hlaviček a ujistěte se, že jsou všechny definice tříd zkompilovány před tím, než se použijí problematické šablony.

  • Konstruktory kopírování

    Ve verzích Visual Studio 2013 i 2015 kompilátor vygeneruje kopírovací konstruktor pro třídu, pokud má tato třída konstruktor přesunu definovaný uživatelem, ale žádný kopírovací konstruktor definovaný uživatelem. V Dev14 je tento implicitně vygenerovaný konstruktor kopírování označen také jako "= delete".

  • main deklarovaný jako extern "C" nyní vyžaduje návratový typ.

    Následující kód teď vytvoří C4430.

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

    Pokud chcete chybu opravit, přidejte návratový typ:

    extern "C" int __cdecl main(){} // OK
    
  • Parametr typename není v inicializátoru člena povolený.

    Následující kód teď vytvoří C2059:

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

    Pokud chcete chybu opravit, odeberte typename ji z inicializátoru:

    S1() : T::type() // OK
    ...
    
  • Třída úložiště u explicitních specializace se ignoruje.

    V následujícím kódu je specifikátor třídy statického úložiště ignorován.

    template <typename T>
    void myfunc(T h)
    {
    }
    
    template<>
    static void myfunc(double h) // static is ignored
    {
    }
    
  • Konstanta použitá v static_assert uvnitř šablony třídy vždy selže.

    Následující kód způsobí, že static_assert vždy selže:

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

    Chcete-li tento problém vyřešit, zabalte hodnotu do struct:

    template <size_t some_value>
    struct constant_false {
        static const bool value = false;
    };
    
    template <size_t some_value>
    struct S1
    {
        static_assert(constant_false<some_value>::value, "default not valid");
    };
    
    //other partial specializations here
    
  • Pravidla vynucená pro předávání deklarací (Platí pouze pro C.)

    Následující kód teď vytvoří C2065:

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

    Chcete-li tento problém vyřešit, přidejte správné předávací deklarace:

    struct token_s;
    typedef int BOOL;
    typedef int INT;
    
    // forward declarations:
    typedef struct token_s TOKEN;
    typedef TOKEN *PTOKEN;
    
    typedef int(*PFNTERM)(PTOKEN, BOOL, INT);
    
  • Konzistentnější vynucování typů ukazatelů funkcí

    Následující kód teď vytvoří C2197:

    typedef int(*F1)(int);
    typedef int(*F2)(int, int);
    
    void func(F1 f, int v1, int v2)
    {
        f(v1, v2); // C2197
    }
    
  • Nejednoznačná volání přetížených funkcí

    Následující kód nyní vyvolá chybu C266: "N::bind": nejednoznačné volání přetížené funkce.

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

    Chcete-li chybu opravit, můžete plně kvalifikovat volání na bind: N::bind(...). Pokud je však tato změna manifestována prostřednictvím nelarovaného identifikátoru (C2065), může být vhodné tuto změnu opravit pomocí using deklarace.

    K tomuto vzoru často dochází u ComPtr a dalších typů v Microsoft::WRL oboru názvů.

  • Oprava nesprávné adresy

    Následující kód vyvolá chybu C2440: '=': nelze převést 'type *' na 'type'. Chybu opravíte tak, že změníte &(typ) na (typ) a (&f()) na (f()).

    // C
    typedef void (*type)(void);
    
    void f(int i, type p);
    void g(int);
    void h(void)
    {
        f(0, &(type)g);
    }
    
    // C++
    typedef void(*type)(void);
    
    type f();
    
    void g(type);
    
    void h()
    {
        g(&f());
    }
    
  • Řetězcový literál je konstantní pole.

    Následující kód nyní vytvoří C2664: 'void f(void )': nemůže převést argument 1 z const char ()[2] na void *.

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

    Pokud chcete chybu opravit, změňte typ parametru funkce na const void*, nebo změňte text h tak, aby vypadal takto:

    void h(void)
    {
        char name[] = __FUNCTION__;
        f( name);
        void *p = &"";
    }
    
  • Řetězce UDL C++11

    Následující kód nyní vytvoří chybu C3688: neplatná přípona literálu 'L'; literálový operátor nebo šablona literálového operátoru 'operátor ""L' nebyla nalezena.

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

    Pokud chcete chybu opravit, změňte kód tak, aby přidal mezeru:

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

    V předchozím MACRO příkladu už není analyzován jako dva tokeny (řetězec následovaný makrem). Nyní se to analyzuje jako jeden token UDL. Totéž platí pro L"L", který byl analyzován dříve jako L a L" a nyní je analyzován jako L a "".

    Pravidla zřetězení řetězců byla rovněž přenesena do souladu se standardem, což znamená, že L"a" "b" je ekvivalentní L"ab". Předchozí edice sady Visual Studio nepřijaly zřetězení řetězců s jinou šířkou znaků.

  • Odebrání prázdného znaku v C++11

    Následující kód nyní generuje chybu C2137: prázdná znaková konstanta

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

    Pokud chcete chybu opravit, změňte kód tak, aby explicitně zobrazoval hodnotu null:

    bool check(wchar_t c){
        return c == L'\0';
    }
    
  • Výjimky MFC nelze zachytit hodnotou, protože nejsou kopírovatelné.

    Následující kód v aplikaci MFC nyní způsobuje chybu C2316: "D": nelze zachytit, protože destruktor a/nebo kopírovací konstruktor jsou nepřístupné nebo odstraněné.

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

    Pokud chcete kód opravit, můžete blok catch změnit na catch (const D &) , ale lepším řešením je obvykle použít makra MFC TRY/CATCH.

  • alignof je teď klíčové slovo.

    Následující kód nyní vytvoří chybu C2332: class: chybějící název značky. Chcete-li opravit kód, musíte přejmenovat třídu nebo, pokud třída provádí stejnou práci jako alignof, stačí nahradit třídu novým klíčovým slovem.

    class alignof{}
    
  • constexpr je teď klíčové slovo.

    Následující kód nyní generuje chybu C2059: syntaktická chyba: ')'. Chcete-li opravit kód, musíte přejmenovat všechny názvy funkcí nebo proměnných, které jsou volána constexpr.

    int constexpr() {return 1;}
    
  • Pohyblivé typy nemohou být const

    Pokud funkce vrátí typ, který má být přesunut, jeho návratový typ by neměl být const.

  • Odstraněné konstruktory kopírování

    Následující kód nyní vytvoří C2280 S::S(S &&): pokouší se odkazovat na odstraněnou funkci:

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

    Pokud chcete chybu opravit, použijte přímou inicializaci pro S2:

    struct S{
        S(int, int);
        S(const S&) = delete;
        S(S&&) = delete;
    };
    
    S s2 = {2,3}; //OK
    
  • Převod na ukazatel funkce se vygeneruje pouze v případě, že se nezachytí lambda

    Následující kód vytvoří C2664 v sadě Visual Studio 2015.

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

    Pokud chcete chybu opravit, odeberte = ze seznamu zachycení.

  • Nejednoznačná volání zahrnující operátory převodu

    Následující kód nyní generuje chybu C2440: Přetypování typu: nelze převést z S2 na S1:

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

    Pokud chcete chybu opravit, explicitně volejte operátor převodu:

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

    Následující kód nyní vytvoří chybu C2593: operátor =je nejednoznačný:

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

    Pokud chcete chybu opravit, explicitně volejte operátor převodu:

    void f(S1 *p, S2 s)
    {
        *p = s.operator S1&();
    }
    
  • Oprava neplatné inicializace kopírování při inicializaci nestatického datového člena (NSDMI)

    Následující kód nyní generuje chybu C2664: S1::S1(S1 &&): Nemůže převést argument 1 z logické hodnoty na const S1 &:

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

    Pokud chcete chybu opravit, použijte přímou inicializaci:

    struct S2 {
    S1 s1{true}; // OK
    };
    
  • Přístup k konstruktorům uvnitř příkazů decltype

    Následující kód nyní vytvoří C2248: S::S: nemůže získat přístup k privátnímu členu deklarovanému ve třídě S:

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

    Chybu opravíte přidáním deklarace přítele pro S2 v S.

    class S {
        S();
        friend class S2; // Make S2 a friend
    public:
        int i;
    };
    
  • Výchozí konstruktor lambda se implicitně odstraní.

    Následující kód nyní generuje chybu C3497: Nelze vytvořit instanci lambda:

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

    Chcete-li chybu opravit, odeberte povinnost volání výchozího konstruktoru. Pokud lambda nic nezachytí, může se přetypovat na ukazatel funkce.

  • Lambdas s odstraněným operátorem přiřazení

    Následující kód nyní vytvoří chybu C2280:

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

    Pokud chcete chybu opravit, nahraďte lambda třídou functoru nebo odeberte potřebu použití operátoru přiřazení.

  • Pokus o přesunutí objektu s odstraněným konstruktorem kopírování

    Následující kód nyní generuje chybu C2280: moveable::moveable(const moveable &): pokus o odkaz na odstraněnou funkci

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

    Pokud chcete chybu opravit, použijte std::move místo toho:

    S(moveable && m) :
        m_m(std::move(m))
    
  • Místní třída nemůže odkazovat na jinou místní třídu definovanou později ve stejné funkci.

    Následující kód nyní generuje chybu C2079: "s" používá nedefinovanou strukturu main::S2.

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

    Chybu opravíte tak, že přesunete definici S2:

    int main()
    {
        struct S2 { //moved up
        };
    
    struct S1 {
        void f() {
            S2 s;
            }
        };
    }
    
  • Nelze volat chráněný základní ctor v těle odvozeného ctoru.

    Následující kód nyní generuje chybu C2248: S1::S1: Nemůže získat přístup k chráněnému členu deklarovanému ve třídě S1.

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

    Pokud chcete chybu opravit, S2 odeberte volání S1() z konstruktoru a v případě potřeby ji vložte do jiné funkce.

  • {} zabraňuje převodu na ukazatel

    Následující kód nyní vytvoří C2439 S::p: člen nelze inicializovat.

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

    Pokud chcete chybu opravit, odstraňte složené závorky kolem 0 nebo jednoduše použijte nullptr, jak je znázorněno v tomto příkladu:

    struct S {
        S() : p(nullptr) {}
        void *p;
    };
    
  • Nesprávná definice a použití makra s kulatými závorkami

    Následující příklad nyní vygeneruje chybu C2008: ;: neočekávaná v definici makra

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

    Pokud chcete tento problém vyřešit, změňte horní čáru na #define A();

    Následující kód vytvoří chybu C2059: syntaktická chyba: ')'

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

    Pokud chcete kód opravit, odeberte mezeru mezi A a ().

    Následující kód způsobí chybu C2091: funkce vrátí funkci:

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

    Chcete-li chybu opravit, odeberte závorky za deklarací v S: DECLARE;.

    Následující kód způsobí chybu C2062: typ int neočekávaně.

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

    Pokud chcete tento problém vyřešit, definujte A ho takto:

    #define A int
    
  • Extra parens v deklaracích

    Následující kód způsobí chybu C2062: typ int neočekávaně.

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

    Chcete-li chybu opravit, odeberte závorky kolem j. Pokud jsou závorky potřeba k přehlednosti, použijte typedef.

  • Konstruktory generované kompilátorem a __declspec(novtable)

    V sadě Visual Studio 2015 existuje větší pravděpodobnost, že kompilátor generované vložené konstruktory abstraktních tříd s virtuálními základními třídami mohou vystavit nesprávné použití __declspec(novtable) při použití v kombinaci s __declspec(dllimport).

  • Auto vyžaduje v přímé inicializaci seznamu jeden výraz.

    Následující kód nyní vytvoří chybu C3518: 'testPositions': v kontextu přímé inicializace seznamu lze typ pro 'auto' odvodit pouze z jednoho výrazu inicializátoru.

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

    Pokud chcete chybu opravit, jednou z možností je inicializace testPositions 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ů a ukazatelů na typy pro is_convertible

    Následující kód nyní způsobí selhání statického tvrzení.

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

    Pokud chcete chybu opravit, změňte static_assert tak, aby porovnával ukazatele na D a B2:

    static_assert(std::is_convertible<D*, B2*>::value, "fail");
    
  • deklarace __declspec(novtable) musí být konzistentní

    __declspec deklarace musí být konzistentní ve všech knihovnách. Následující kód teď vytvoří porušení pravidla odr (one-definition rule):

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

Vylepšení shody v aktualizaci Update 1

  • Privátní virtuální základní třídy a nepřímá dědičnost

    Předchozí verze kompilátoru umožnily odvozené třídě volat členské funkce jeho nepřímo odvozené private virtual základní třídy. Toto staré chování bylo nesprávné a neodpovídá standardu C++. Kompilátor už nepřijímá kód napsaný tímto způsobem a v důsledku toho vydává chybu kompilátoru C2280.

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

    Příklad (před)

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

    Příklad (po)

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

    - nebo -

    class base;  // as above
    
    class middle : private virtual base {};
    class top : public virtual middle, private virtual bottom {};
    
    void destroy(top *p)
    {
        delete p;
    }
    
  • Přetížený operátor new a operátor delete

    Předchozí verze kompilátoru umožňovaly, aby nečlenové operátor new a operator delete byly deklarovány jako statické a deklarovány v jiných oborech názvů než v globálním oboru názvů. Toto staré chování vytvářelo riziko, že program nebude volat implementaci operátora new nebo delete, kterou zamýšlel programátor, což mohlo vést k tichému nesprávnému chování během běhu programu. Kompilátor už nepřijímá kód napsaný tímto způsobem a místo toho vydává chybu kompilátoru C2323.

    error C2323: 'operator new': non-member operator new or delete functions may not be declared static or in a namespace other than the global namespace.
    

    Příklad (před)

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

    Příklad (po)

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

    Kromě toho, i když kompilátor neposkytuje konkrétní diagnostiku, vložený operátor new se považuje za špatně vytvořený.

  • Volání operátoru type() (převod definovaný uživatelem) u jiných typů než tříd

    Předchozí verze kompilátoru umožňovaly volat "operator type()" u typů, které nejsou třídami, přičemž to tiše ignoroval. Toto staré chování vytvořilo riziko tichého špatného generování kódu, což vedlo k nepředvídatelným chování modulu runtime. Kompilátor už nepřijímá kód napsaný tímto způsobem a místo toho vydává chybu kompilátoru C2228.

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

    Příklad (před)

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

    Příklad (po)

    typedef int index_t;
    void bounds_check(index_t index);
    void login(int column)
    {
        bounds_check(column);  // removed cast to 'index_t', 'index_t' is an alias of 'int'
    }
    
  • Redundantní název typu v propracovaných specifikátorech typů

    Předchozí verze kompilátoru umožňovaly typename ve specifikátoru detailního typu, ale kód napsaný tímto způsobem je sémanticky nesprávný. Kompilátor už nepřijímá kód napsaný tímto způsobem a místo toho vydává chybu kompilátoru C3406.

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

    Příklad (před)

    template <typename class T>
    class container;
    

    Příklad (po)

    template <class T>  // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case
    class container;
    
  • Odedukování typu pole ze seznamu inicializátorů

    Předchozí verze kompilátoru nepodporují odpočty typů polí ze seznamu inicializátorů. Kompilátor teď podporuje tuto formu odpočtu typů a v důsledku toho může být volání šablon funkcí pomocí seznamů inicializátorů nejednoznačné nebo může být zvoleno jiné přetížení než v předchozích verzích kompilátoru. Chcete-li tyto problémy vyřešit, program teď musí explicitně určit přetížení zamýšlené programátorem.

    Když toto nové chování způsobí řešení přetížení zvážit další kandidáta, který je stejně dobrý jako historický kandidát, volání se stane nejednoznačným a kompilátor vydá chybu kompilátoru C2668 jako výsledek.

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

    Příklad 1: Nejednoznačné volání přetížené funkce (před)

    // In previous versions of the compiler, code written in this way would unambiguously call f(int, Args...)
    template < typename... Args>
    void f(int, Args...);  //
    
    template < int N, typename... Args>
    void f(const int(&)[N], Args...);
    
    int main()
    {
        // The compiler now considers this call ambiguous, and issues a compiler error
         f({ 3 });   error C2668 : 'f' ambiguous call to overloaded function
    }
    

    Příklad 1: nejednoznačné volání přetížené funkce (následně)

    template < typename... Args>
    void f(int, Args...);  //
    
    template < int N, typename... Args>
    void f(const int(&)[N], Args...);
    
    int main()
    {
        // To call f(int, Args...) when there is just one expression in the initializer list, remove the braces from it.
        f(3);
    }
    

    Když toto nové chování způsobí, že při řešení přetížení je uvažován další kandidát, který lépe odpovídá než historický kandidát, volání se jednoznačně vyřeší na nového kandidáta, což způsobí změnu chování programu, která se pravděpodobně odlišuje od toho, co programátor zamýšlel.

    Příklad 2: změna rozlišení přetížení (před)

    // In previous versions of the compiler, code written in this way would unambiguously call f(S, Args...)
    struct S
    {
        int i;
        int j;
    };
    
    template < typename... Args>
    void f(S, Args...);
    
    template < int N, typename... Args>
    void f(const int *&)[N], Args...);
    
    int main()
    {
        // The compiler now resolves this call to f(const int (&)[N], Args...) instead
         f({ 1, 2 });
    }
    

    Příklad 2: změna vyhodnocení přetížení (po)

    struct S;  // as before
    
    template < typename... Args>
    void f(S, Args...);
    
    template < int N, typename... Args>
    void f(const int *&)[N], Args...);
    
    int main()
    {
        // To call f(S, Args...), perform an explicit cast to S on the initializer list.
        f(S{ 1, 2 });
    }
    
  • Obnovení upozornění příkazu switch

    Předchozí verze kompilátoru odebrala některá upozornění související s switch příkazy. Tato upozornění se teď obnovila. Kompilátor nyní vydává obnovená varování a varování související s konkrétními případy (včetně výchozího případu) jsou nyní vydána na řádku obsahujícím problematický případ, nikoli na posledním řádku switch výrazu. V důsledku toho, že nyní tato upozornění vydáváte na různých řádcích než v minulosti, upozornění, která byla dříve potlačena použitím #pragma warning(disable:####) , už nemusí být potlačena tak, jak má. Chcete-li tato upozornění potlačit, jak bylo zamýšleno, může být nutné přesunout direktivu #pragma warning(disable:####) na řádek nad prvním případem chyby. Toto jsou obnovená upozornění:

    warning C4060: switch statement contains no 'case' or 'default' labels
    
    warning C4061: enumerator 'bit1' in switch of enum 'flags' is not explicitly handled by a case label
    
    warning C4062: enumerator 'bit1' in switch of enum 'flags' is not handled
    
    warning C4063: case 'bit32' is not a valid value for switch of enum 'flags'
    
    warning C4064: switch of incomplete enum 'flags'
    
    warning C4065: switch statement contains 'default' but no 'case' labels
    
    warning C4808: case 'value' is not a valid value for switch condition of type 'bool'
    
    Warning C4809: switch statement has redundant 'default' label; all possible 'case' labels are given
    

    Příklad C4063 (před)

    class settings
    {
    public:
        enum flags
        {
            bit0 = 0x1,
            bit1 = 0x2,
            ...
        };
        ...
    };
    
    int main()
    {
        auto val = settings::bit1;
    
        switch (val)
        {
        case settings::bit0:
            break;
    
        case settings::bit1:
            break;
    
             case settings::bit0 | settings::bit1:  // warning C4063
                break;
        }
    }
    

    Příklad C4063 (po)

    class settings { ... };  // as above
    int main()
    {
        // since C++11, use std::underlying_type to determine the underlying type of an enum
        typedef std::underlying_type< settings::flags> ::type flags_t;
    
            auto val = settings::bit1;
    
        switch (static_cast< flags_t> (val))
        {
        case settings::bit0:
            break;
    
        case settings::bit1:
            break;
    
        case settings::bit0 | settings::bit1:  // ok
            break;
        }
    };
    

    Příklady dalších obnovených upozornění jsou uvedeny v jejich dokumentaci.

  • #include: použití specifikátoru rodičovského adresáře .. v názvu cesty (týká se pouze /Wall/WX)

    Předchozí verze kompilátoru nezjistily použití specifikátoru nadřazeného adresáře .. v cestě direktiv #include. Kód napsaný tímto způsobem je obvykle určen k zahrnutí hlaviček, které existují mimo projekt nesprávným použitím cest relativních k projektu. Toto staré chování vytvořilo riziko, že program může být kompilován zahrnutím jiného zdrojového souboru, než je zamýšlený programátor, nebo že tyto relativní cesty nebudou přenosné do jiných prostředí sestavení. Kompilátor teď rozpozná a upozorní programátora na kód napsaný tímto způsobem a v případě povolení vydá volitelné upozornění kompilátoru C4464.

    warning C4464: relative include path contains '..'
    

    Příklad (před)

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

    Příklad (po)

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

    Kromě toho, i když kompilátor neposkytuje konkrétní diagnostiku, doporučujeme, aby specifikátor nadřazeného adresáře "." neměl být použit k určení adresářů zahrnutí projektu.

  • #pragma optimize() přesahuje konec souboru hlavičky (pouze ovlivňuje /Wall/WX)

    Předchozí verze kompilátoru nedetekovaly změny nastavení příznaků optimalizace, které uniknou z hlavičkového souboru, jenž je zahrnut v překladové jednotce. Kompilátor nyní detekuje a upozorní programátora na kód napsaný tímto způsobem a v případě povolení vydá volitelné varování kompilátoru C4426 v místě chybného #include. Toto upozornění se vydává pouze v případě, že změny kolidují s příznaky optimalizace nastavené argumenty příkazového řádku kompilátoru.

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

    Příklad (před)

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

    Příklad (po)

    // C4426.h
    #pragma optimize("g", off)
                ...
    #pragma optimize("", on)  // restores optimization flags set via command-line arguments
    // C4426.h ends
    
    // C4426.cpp
    #include "C4426.h"
    
  • Neshoda #pragma warning(push) a #pragma warning(pop) (ovlivňuje pouze /Wall/WX)

    Předchozí verze kompilátoru nezjistily #pragma warning(push) změny stavu spárované se #pragma warning(pop) změnami stavu v jiném zdrojovém souboru, který je zřídka zamýšlený. Toto staré chování vytvořilo riziko, že program bude zkompilován s jinou sadou povolených upozornění, než programátor zamýšlel, což může v tichosti vést ke špatnému chování běhového prostředí. Kompilátor nyní rozpozná a upozorní programátora na kód napsaný tímto způsobem a vydá volitelné upozornění kompilátoru C5031 v umístění odpovídajícího #pragma warning(pop), pokud je povoleno. Toto upozornění obsahuje poznámku odkazující na umístění odpovídajícího #pragma warning(push).

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

    Příklad (před)

    // C5031_part1.h
    #pragma warning(push)
    #pragma warning(disable:####)
    ...
    // C5031_part1.h ends without #pragma warning(pop)
    
    // C5031_part2.h
    ...
    #pragma warning(pop)  // pops a warning state not pushed in this source file
    ...
    // C5031_part1.h ends
    
    // C5031.cpp
    #include "C5031_part1.h" // leaves #pragma warning(push) 'dangling'
    ...
    #include "C5031_part2.h" // matches 'dangling' #pragma warning(push), resulting in warning C5031
    ...
    

    Příklad (po)

    // C5031_part1.h
    #pragma warning(push)
    #pragma warning(disable:####)
    ...
    #pragma warning(pop)  // pops the warning state pushed in this source file
    // C5031_part1.h ends without #pragma warning(pop)
    
    // C5031_part2.h
    #pragma warning(push)  // pushes the warning state pushed in this source file
    #pragma warning(disable:####)
    ...
    #pragma warning(pop)
    // C5031_part1.h ends
    
    // C5031.cpp
    #include "C5031_part1.h" // #pragma warning state changes are self-contained and independent of other source files or their #include order.
    ...
    #include "C5031_part2.h"
    ...
    

    Ačkoli vzácně, je kód napsaný tímto způsobem někdy úmyslný. Kód napsaný tímto způsobem je citlivý na změny v #include pořadí. Pokud je to možné, doporučujeme, aby soubory zdrojového kódu spravovaly stav upozornění samostatně.

  • Nedostupné #pragma upozornění (nabízení) (pouze ovlivňuje /Wall/WX)

    Předchozí verze kompilátoru nedokázaly detekovat nesrovnalosti změn stavu #pragma warning(push) na konci překladové jednotky. Kompilátor nyní rozpozná a upozorní programátora na kód napsaný tímto způsobem a vydá volitelné upozornění kompilátoru C5032 na místě, kde se vyskytuje nesoulad s #pragma warning(push), pokud je povoleno. Toto upozornění se vydává pouze v případě, že v jednotce překladu nejsou žádné chyby kompilace.

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

    Příklad (před)

    // C5032.h
    #pragma warning(push)
    #pragma warning(disable:####)
    ...
    // C5032.h ends without #pragma warning(pop)
    
    // C5032.cpp
    #include "C5032.h"
    ...
    // C5032.cpp ends -- the translation unit is completed without #pragma warning(pop), resulting in warning C5032 on line 1 of C5032.h
    

    Příklad (následující)

    // C5032.h
    #pragma warning(push)
    #pragma warning(disable:####)
    ...
    #pragma warning(pop) // matches #pragma warning (push) on line 1
    // C5032.h ends
    
    // C5032.cpp
    #include "C5032.h"
    ...
    // C5032.cpp ends -- the translation unit is completed without unmatched #pragma warning(push)
    
  • V důsledku vylepšeného sledování stavu upozornění #pragma mohou být vydána další upozornění.

    Předchozí verze kompilátoru sledovaly změny stavu upozornění #pragma nedostatečně dobře k tomu, aby vydaly všechna zamýšlená upozornění. Toto chování vytvořilo riziko, že určitá upozornění by byla účinně potlačena za jiných okolností, než jaké zamýšlel programátor. Kompilátor nyní sleduje #pragma warning stav robustněji – zejména související se #pragma warning změnami stavu uvnitř šablon – a volitelně vydává nová upozornění C5031 a C5032, které jsou určeny k tomu, aby programátoru pomohl najít nezamýšlené použití #pragma warning(push) a #pragma warning(pop).

    V důsledku vylepšeného #pragma warning sledování změn stavu mohou být nyní vydána upozornění, která byla dříve nesprávně potlačována, nebo upozornění související s problémy, které byly dříve chybně diagnostikovány.

  • Vylepšená identifikace nedostupného kódu

    Změny standardní knihovny jazyka C++ a vylepšená schopnost volání vložených funkcí v předchozích verzích kompilátoru může kompilátoru umožnit prokázat, že určitý kód je nyní nedostupný. Toto nové chování může vést k novým a častěji vydávaným instancím upozornění C4720.

    warning C4720: unreachable code
    

    V mnoha případech může být toto upozornění vydáno pouze při kompilaci s povolenými optimalizacemi, protože optimalizace můžou vyřaizovat více volání funkcí, eliminovat redundantní kód nebo jinak zajistit, že určitý kód je nedostupný. Zjistili jsme, že nové instance upozornění C4720 se často vyskytly v blocích try/catch , zejména v souvislosti s použitím příkazu std::find.

    Příklad (před)

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

    Příklad (po)

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

Vylepšení shody v aktualizaci Update 2

  • V důsledku částečné podpory výrazu SFINAE mohou být vydána další upozornění a chyby.

    Předchozí verze kompilátoru neanalyzovali určité druhy výrazů uvnitř decltype specifikátorů kvůli nedostatku podpory výrazu SFINAE. Toto staré chování bylo nesprávné a neodpovídá standardu C++. Kompilátor teď tyto výrazy parsuje a má částečnou podporu výrazu SFINAE kvůli probíhajícím vylepšením shody. Kompilátor proto nyní vydává upozornění a chyby zjištěné ve výrazech, které předchozí verze kompilátoru neanalyly.

    Když toto nové chování analyzuje decltype výraz, který obsahuje typ, který ještě nebyl deklarován, kompilátor vydá chybu kompilátoru C2039 jako výsledek.

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

    Příklad 1: použití nedelarovaného typu (před)

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

    Příklad 1 (poté)

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

    Když toto nové chování analyzuje decltype výraz, ve kterém chybí nezbytné použití klíčového slova typename k označení, že závislý název je typ, kompilátor vydá upozornění kompilátoru C4346 společně s chybou kompilátoru C2923.

    warning C4346: 'S2<T>::Type': dependent name is not a type
    
    error C2923: 's1': 'S2<T>::Type' is not a valid template type argument for parameter 'T'
    

    Příklad 2: Závislý název není typem (před)

    template < typename T>
    struct s1
    {
        typedef T type;
    };
    
    template < typename T>
    struct s2
    {
        typedef T type;
    };
    
    template < typename T>
    T declval();
    
    struct s
    {
        template < typename T>
        auto f(T t) - > decltype(t(declval< S1< S2< T> ::type> ::type> ()));  // warning C4346, error C2923
    };
    

    Příklad 2 (po)

    template < typename T> struct s1 { ... };  // as above
    template < typename T> struct s2 { ... };  // as above
    
    template < typename T>
    T declval();
    
    struct s
    {
        template < typename T>
        auto f(T t) - > decltype(t(declval< S1< typename S2< T> ::type> ::type> ()));
    };
    
  • volatile členské proměnné brání implicitně definovaným konstruktorům a operátorům přiřazení.

    Předchozí verze kompilátoru povolily třídu, která má volatile členské proměnné, aby byly automaticky generovány výchozí konstruktory kopírování/přesunutí a výchozí operátory přiřazení kopírování/přesunutí. Toto staré chování bylo nesprávné a neodpovídá standardu C++. Kompilátor nyní považuje třídu, která má členské proměnné volatile, za třídu s netriviálními operátory konstrukce a přiřazení, což brání automatickému generování výchozích implementací těchto operátorů. Pokud je taková třída členem sjednocení (nebo anonymní sjednocení uvnitř třídy), konstruktory kopírování/přesunutí a operátory přiřazení kopírování/přesunutí sjednocení (nebo třídy obsahující anonymní sjednocení) budou implicitně definovány jako odstraněné. Pokus o vytvoření nebo zkopírování sjednocení (nebo třídy obsahující anonymní sjednocení) bez explicitního definování je chyba a kompilátor vydává chybu kompilátoru C2280 v důsledku toho.

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

    Pří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 C2280
    

    Pří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 C2280
    
  • Statické členské funkce nepodporují cv-kvalifikátory.

    Předchozí verze sady Visual Studio 2015 umožňovaly statické členské funkce mít kvalifikátory cv. Toto chování je způsobeno regresí v sadě Visual Studio 2015 a Visual Studio 2015 Update 1; Visual Studio 2013 a předchozí verze kompilátoru zamítají kód napsaný tímto způsobem. Chování sady Visual Studio 2015 a Visual Studio 2015 Update 1 je nesprávné a neodpovídá standardu C++. Visual Studio 2015 Update 2 odmítne kód napsaný tímto způsobem a místo toho vydá chybu kompilátoru C2511.

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

    Příklad (před)

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

    Příklad(po)

    struct A
    {
        static void func();
    };
    
    void A::func() {}  // removed const
    
  • Předběžná deklarace výčtu není v kódu WinRT povolena (pouze ovlivňuje /ZW)

    Kód zkompilovaný pro prostředí Windows Runtime (WinRT) neumožňuje předsazení deklarace typů pomocí enum, podobně jako při kompilaci spravovaného kódu C++ pro rozhraní .Net Framework s použitím přepínače kompilátoru /clr. Toto chování zajišťuje, že velikost výčtu je vždy známá a lze ji správně promítat do systému typů WinRT. Kompilátor odmítne kód napsaný tímto způsobem a vydá chybu kompilátoru C2599 společně s chybou kompilátoru C3197.

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

    Příklad (před)

    namespace A {
        public enum class CustomEnum : int32;  // forward declaration; error C2599, error C3197
    }
    
    namespace A {
        public enum class CustomEnum : int32
        {
            Value1
        };
    }
    
    public ref class Component sealed
    {
    public:
        CustomEnum f()
        {
            return CustomEnum::Value1;
        }
    };
    

    Příklad (po)

              // forward declaration of CustomEnum removed
    namespace A {
        public enum class CustomEnum : int32
        {
            Value1
        };
    }
    
    public ref class Component sealed
    {
    public:
        CustomEnum f()
        {
            return CustomEnum::Value1;
        }
    };
    
  • Přetížený nečlenský operátor new a operátor delete nemusí být deklarovány jako inline (úroveň 1 (/W1) ve výchozím nastavení).

    Předchozí verze kompilátoru nevydávají upozornění, pokud jsou operátory new a delete, které nejsou členy, deklarovány inline. Kód napsaný tímto způsobem je nesprávně utvořený (není požadována diagnostika) a může způsobit problémy s pamětí způsobené nesouhlasem mezi operátory new a delete (zejména při použití společně s alokací velikosti), které může být obtížné diagnostikovat. Kompilátor teď vydává upozornění kompilátoru C4595, aby pomohl identifikovat kód napsaný tímto způsobem.

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

    Příklad (před)

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

    Příklad (po)

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

    Oprava kódu napsaného tímto způsobem může vyžadovat, aby definice operátorů byly přesunuty z hlavičkového souboru a do odpovídajícího zdrojového souboru.

Vylepšení shody v aktualizaci Update 3

  • std::is_convertable teď detekuje vlastní přiřazení (standardní knihovna).

    Předchozí verze vlastnosti typu std::is_convertable nezjistily správně samopřiřazení typu třídy, pokud je jeho kopírovací konstruktor odstraněn nebo soukromý. Nyní je std::is_convertable<>::value správně nastaven na false při použití na typ třídy se smazaným nebo privátním konstruktorem kopírování.

    K této změně není přidružená žádná diagnostika kompilátoru.

    Příklad

    #include <type_traits>
    
    class X1
    {
                public:
                X1(const X1&) = delete;
                };
    
    class X2
    {
                private:
                X2(const X2&);
                };
    
    static_assert(std::is_convertible<X1&, X1>::value, "BOOM");static_assert(std::is_convertible<X2&, X2>::value, "BOOM");
    

    V předchozích verzích kompilátoru statické aserce v dolní části tohoto příkladu projdou, protože byl std::is_convertable<>::value nesprávně nastaven na true. std::is_convertable<>::value Nyní je správně nastaven na false, což způsobuje selhání statických asercí.

  • Výchozí nebo odstraněné triviální kopírovací a přenosové konstruktory respektují specifikátory přístupu.

    Předchozí verze kompilátoru neprováděly kontrolu přístupového specifikátoru výchozích nebo odstraněných triviálních konstruktorů kopírování a přesunutí před povolením jejich zavolání. Toto staré chování bylo nesprávné a neodpovídá standardu C++. V některých případech toto staré chování vytvořilo riziko tichého chybného generování kódu, což vede k nepředvídatelným chováním za běhu. Kompilátor teď zkontroluje specifikátor přístupu standardně nebo smazaně triviálních kopírovacích a přesunovacích konstruktorů, aby určil, zda může být volán, a pokud ne, vydá upozornění kompilátoru C2248.

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

    Příklad (před)

    class S {
    public:
        S() = default;
    private:
        S(const S&) = default;
    };
    
    void f(S);  // pass S by value
    
    int main()
    {
        S s;
        f(s);  // error C2248, can't invoke private copy constructor
    }
    

    Příklad (po)

    class S {
    public:
        S() = default;
    private:
        S(const S&) = default;
    };
    
    void f(const S&);  // pass S by reference
    
    int main()
    {
        S s;
        f(s);
    }
    
  • Vyřazení podpory kódu ATL s atributy (úroveň 1 (/W1) ve výchozím nastavení)

    Předchozí verze kompilátoru podporovaly kód ATL s atributy. Jako další fáze odebrání podpory pro atributovaný kód ATL, který začal v sadě Visual Studio 2008, byl atributovaný kód ATL označen jako zastaralý. Kompilátor teď vydává upozornění kompilátoru C4467, aby pomohl identifikovat tento druh zastaralého kódu.

    warning C4467: Usage of ATL attributes is deprecated
    

    Pokud chcete pokračovat v používání kódu ATL s atributy, dokud nebude podpora odebrána z kompilátoru, můžete toto upozornění zakázat předáním /Wv:18/wd:4467 argumentů příkazového řádku kompilátoru nebo přidáním #pragma warning(disable:4467) do zdrojového kódu.

    Příklad 1 (před)

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

    Příklad 1 (po)

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

    Někdy možná budete potřebovat nebo chcete vytvořit soubor IDL, abyste se vyhnuli zastaralým atributům ATL, jako v ukázkovém kódu níže.

    Příklad 2 (před)

    [emitidl];
    [module(name = "Foo")];
    
    [object, local, uuid("9e66a290-4365-11d2-a997-00c04fa37ddb")]
    __interface ICustom {
        HRESULT Custom([in] long l, [out, retval] long *pLong);
        [local] HRESULT CustomLocal([in] long l, [out, retval] long *pLong);
    };
    
    [coclass, appobject, uuid("9e66a294-4365-11d2-a997-00c04fa37ddb")]
    class CFoo : public ICustom
    {
        // ...
    };
    

    Nejprve vytvořte soubor *.idl; vygenerovaný soubor vc140.idl lze použít k získání souboru *.idl obsahujícího rozhraní a poznámky.

    Dále do sestavení přidejte krok MIDL, abyste měli jistotu, že se vygenerují definice rozhraní C++.

    Příklad 2 IDL (za)

    import "docobj.idl";
    
    [
        object, local, uuid(9e66a290 - 4365 - 11d2 - a997 - 00c04fa37ddb)
    ]
    
    interface ICustom : IUnknown {
        HRESULT  Custom([in] long l, [out, retval] long *pLong);
        [local] HRESULT  CustomLocal([in] long l, [out, retval] long *pLong);
    };
    
    [version(1.0), uuid(29079a2c - 5f3f - 3325 - 99a1 - 3ec9c40988bb)]
    library Foo
    {
        importlib("stdole2.tlb");
    importlib("olepro32.dll");
    [
        version(1.0),
        appobject,uuid(9e66a294 - 4365 - 11d2 - a997 - 00c04fa37ddb)
    ]
    
    coclass CFoo {
        interface ICustom;
    };
    }
    

    Pak použijte ATL přímo v implementačním souboru, jak je znázorněno v ukázkovém kódu níže.

    Příklad 2 Implementace (poté)

    #include <idl.header.h>
    #include <atlbase.h>
    
    class ATL_NO_VTABLE CFooImpl :
        public ICustom,
        public ATL::CComObjectRootEx< CComMultiThreadModel>
    {
    public:
        BEGIN_COM_MAP(CFooImpl)
            COM_INTERFACE_ENTRY(ICustom)
        END_COM_MAP()
    };
    
  • Předkompilované soubory hlaviček (PCH) a neshodované direktivy #include (pouze ovlivňuje /Wall/WX)

    Předchozí verze kompilátoru přijímaly neshodné příkazy #include ve zdrojových souborech mezi kompilacemi -Yc a -Yu při použití předkompilovaných hlaviček (PCH). Kód napsaný tímto způsobem už kompilátor nepřijímá. Kompilátor teď vydává upozornění kompilátoru CC4598, které pomáhá identifikovat neshodované #include direktivy při použití souborů PCH.

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

    Příklad (před):

    X.cpp (-Ycc.h)

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

    Z.cpp (-Yuc.h)

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

    Příklad (po)

    X.cpp (-Ycc.h)

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

    Z.cpp (-Yuc.h)

    #include "a.h"
    #include "b.h" // matched order relative to X.cpp
    #include "c.h"
    
  • Předkompilované soubory hlaviček (PCH) a nesprávné adresáře zahrnutí (pouze ovlivňuje /Wall/WX)

    Předchozí verze kompilátoru akceptovaly neshodu, včetně argumentů příkazového řádku () adresáře (-I) kompilátoru mezi -Yc kompilacemi a -Yu při použití předkompilovaných souborů hlaviček (PCH). Kód napsaný tímto způsobem už kompilátor nepřijímá. Kompilátor nyní vydává upozornění kompilátoru CC4599, aby pomohl identifikovat nesouladné argumenty příkazového řádku pro adresář zahrnutí -I, když používáte soubory PCH.

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

    Příklad (před)

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

    Příklad (po)

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

Změny shody sady Visual Studio 2013

kompilátor

  • Poslední klíčové slovo teď vygeneruje nevyřešenou chybu symbolu, kde by se zkompilovala dříve:

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

    V dřívějších verzích nebyla vydána chyba, protože volání bylo virtual volání; přestože by ale program za běhu selhal. Nyní je vydána chyba linkeru, protože třída je známa jako konečná. V tomto příkladu chcete-li opravit chybu, byste měli propojit objekt, který obsahuje definici S2::f.

  • Při použití přátelských funkcí v oborech názvů je nutné tyto funkce znovu deklarovat před jejich použitím, jinak se zobrazí chyba, protože kompilátor teď odpovídá standardu ISO C++. Například tento příklad se už nekompiluje:

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

    Chcete-li tento kód opravit, deklarujte friend funkci:

    namespace NS {
        class C {
            void func(int);
            friend void func(C* const) {}
        };
    
        void func(C* const);  // conforming fix
    
        void C::func(int) {
            NS::func(this);
        }
    
  • Standard C++ neumožňuje explicitní specializaci ve třídě. Přestože kompilátor jazyka Microsoft C++ umožňuje v některých případech, například v následujícím příkladu, je nyní vygenerována chyba, protože kompilátor nepovažuje druhou funkci za specializaci prvního.

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

    Chcete-li tento kód opravit, upravte druhou funkci:

    template <> void f(char& val);
    
  • Kompilátor se už nepokusí tyto dvě funkce v následujícím příkladu nejednoznačit a teď vygeneruje chybu:

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

    Chcete-li tento kód opravit, upřesněte volání:

    template< typename T> void Func(T* t = nullptr);
    template< typename T> void Func(...);
    
    int main() {
        Func< int>(nullptr); // ok
    }
    
  • Než kompilátor odpovídal standardu ISO C++11, následující kód by se zkompiloval a způsobil, že by se x vyřešilo na typ int:

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

    Tento kód nyní vyřeší x na typ std::initializer_list<int> a způsobí chybu na dalším řádku, když se pokusí přiřadit x k typu int. (Ve výchozím nastavení neexistuje žádný převod.) Chcete-li tento kód opravit, použijte int k nahrazení auto:

    int x = {0};
    int y = x;
    
  • Agregační inicializace již není povolena, pokud typ hodnoty vpravo neodpovídá typu inicializované hodnoty vlevo a je vydána chyba, protože standard ISO C++11 vyžaduje jednotné inicializace, aby fungovala bez zužování převodů. Pokud byl dříve k dispozici zužující převod, by bylo místo chyby vydáno kompilátorové upozornění (úroveň 4) C4242.

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

    Chcete-li tento kód opravit, přidejte explicitní zužující převod:

    int i = 0;
    char c = {static_cast<char>(i)};
    
  • Následující inicializace už není povolená:

    void *p = {{0}};
    

    Chcete-li tento kód opravit, použijte některou z těchto forem:

    void *p = 0;
    // or
    void *p = {0};
    
  • Vyhledávání názvů se změnilo. Následující kód se v kompilátoru C++ v sadě Visual Studio 2012 a Visual Studio 2013 vyřeší jinak:

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

    Ve Visual Studiu 2012 byl výraz E1::b vyhodnocen na ::E1 v globálním oboru. Ve Visual Studiu 2013 se E1 ve výrazu E1::b řeší jako typedef E2 definice v main() a má typ ::E2.

  • Změnilo se rozložení objektu. Na platformě x 64 se může v porovnání z předchozími verzemi změnit rozložení objektů třídy. Pokud má virtual funkci, ale nemá základní třídu, která má virtual funkci, objektový model kompilátoru vloží ukazatel na virtual tabulku funkcí za rozložení datového člena. To znamená, že rozložení nemusí být ve všech případech optimální. V předchozích verzích se optimalizace pro platformu x64 pokoušela vylepšit rozložení za vás, ale protože ve složitých situacích s kódem nefungovala správně, byla odebrána ve Visual Studio 2013. Podívejte se například na tento kód:

    __declspec(align(16)) struct S1 {
    };
    
    struct S2 {
        virtual ~S2();
        void *p;
        S1 s;
    };
    
  • Ve Visual Studio 2013 je výsledek sizeof(S2) na x64 48, ale v předchozích verzích se hodnotil jako 32. Chcete-li provést toto vyhodnocení na hodnotu 32 v kompilátoru jazyka C++ sady Visual Studio 2013 pro x64, přidejte fiktivní základní třídu, která má virtual funkci:

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

    Pokud chcete najít místa v kódu, která by se dřívější verze pokusila optimalizovat, použijte kompilátor z této verze společně s možností kompilátoru /W3 a zapněte upozornění C4370. Příklad:

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

    Před sadou Visual Studio 2013 tento kód vypíše tuto zprávu: "upozornění C4370: S2: rozložení třídy se změnilo z předchozí verze kompilátoru kvůli lepšímu balení".

    Kompilátor x86 má stejný neoptimální problém s rozložením ve všech verzích kompilátoru. Pokud je například tento kód je zkompilován pro platformu x86:

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

    Výsledek sizeof(S) je 24. Pokud ale použijete alternativní řešení uvedené pro platformu x64, můžete ho snížit na 16:

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

Standardní knihovna

Kompilátor C++ v sadě Visual Studio 2013 detekuje neshody v _ITERATOR_DEBUG_LEVEL, které byly implementovány v sadě Visual Studio 2010 a neshody RuntimeLibrary. K těmto neshodám dochází, když jsou možnosti kompilátoru /MT (statická verze), /MTd (statické ladění), /MD (dynamická verze) a /MDd (dynamické ladění) smíšené.

  • Pokud váš kód uznává šablony simulovaných aliasů předchozí verze, musíte ho změnit. Například místo allocator_traits<A>::rebind_alloc<U>::other, teď musíte říct allocator_traits<A>::rebind_alloc<U>. Přestože ratio_add<R1, R2>::type již není nutný a nyní doporučujeme použít ratio_add<R1, R2>, stále se první zkompiluje, protože ratio<N, D> musí mít definován "typ" pro snížený poměr, což bude stejný typ, pokud již je snížen.

  • Musíte použít #include <algorithm> při volání std::min() nebo std::max().

  • Pokud váš stávající kód používá simulované výčty s oborem z předchozí verze – tradiční neskopové výčty zabalené v jmenných prostorech – musíte ho změnit. Pokud jste například odkazovali na typ std::future_status::future_status, teď musíte říct std::future_status. Většina kódu ale nemá vliv – například std::future_status::ready se stále kompiluje.

  • explicit operator bool() je přísnější než operátor unspecified-bool-type(). explicit operator bool() umožňuje explicitní konverze na bool – například pokud je dáno shared_ptr<X> sp, pak jsou obě static_cast<bool>(sp) a bool b(sp) platné – a Boolean-testovatelné "kontextové konverze" na bool – například if (sp), !sp, sp &&. explicit operator bool() však zakazuje implicitní převody na booleovskou hodnotu, takže nemůžete říci bool b = sp; a protože je návratový typ bool, nemůžete říci return sp.

  • Teď, když jsou implementované skutečné variadické šablony, _VARIADIC_MAX a související makra nemají žádný vliv. Pokud stále definujete _VARIADIC_MAX, bude ignorován. Pokud jste uznali naše makrosystémy určené k podpoře simulovaných variadic šablon jakýmkoliv jiným způsobem, musíte změnit váš kód.

  • Kromě běžných klíčových slov teď hlavičky standardní knihovny jazyka C++ zakázaly nahrazení makra kontextově citlivých klíčových slov override a final.

  • reference_wrapper, ref(), a cref() nyní zakazují vazbu na dočasné objekty.

  • <random> nyní přísně vynucuje své předpoklady času kompilace.

  • Různé vlastnosti standardní knihovny jazyka C++ mají předběžnou podmínku "T musí být úplný typ". Přestože kompilátor nyní tuto předběžnou podmínku vynucuje přísněji, nemusí ji vynutit ve všech situacích. (Vzhledem k tomu, že porušení předpokladů standardní knihovny C++ aktivují nedefinované chování, standard nezaručuje vynucení.)

  • Standardní knihovna C++ nepodporuje /clr:oldSyntax.

  • Specifikace C++11 pro common_type<> měla neočekávané a nežádoucí důsledky; konkrétně způsobuje, že common_type<int, int>::type vrací int&&. Proto kompilátor implementuje návrh řešení problému 2141, který navrhla pracovní skupina pro knihovny, aby common_type<int, int="">::type vracelo int.

    Jako vedlejší účinek této změny už případ identity nefunguje (common_type<T> ne vždy vede k typu T). Toto chování odpovídá navrhovanému řešení, ale přeruší veškerý kód, který se spoléhal na předchozí chování.

    Pokud potřebujete atribut identity, nepoužívejte nestandardní std::identity, definovaný v <type_traits>, neboť nebude fungovat pro <void>. Místo toho implementujte vlastní typovou vlastnost identity tak, aby vyhovovala vašim potřebám. Tady je příklad:

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

MFC a ATL

  • Visual Studio 2013 Pouze: Knihovna MFC MBCS není součástí Visual Studio, protože Unicode je tak populární a použití kódování MBCS výrazně pokleslo. Tato změna také udržuje MFC lépe sladěné s Windows SDK, protože mnoho nových ovládacích prvků a zpráv je pouze pro Unicode. Pokud však budete muset i nadále používat knihovnu MFC MBCS, můžete ji stáhnout z webu Stažení softwaru společnosti Microsoft na vícebajtové knihovně MFC pro Visual Studio 2013. Distribuovatelný balíček Visual C++ stále zahrnuje i tuto knihovnu. (Poznámka: Knihovna MBCS DLL je součástí součástí instalačních komponent jazyka C++ v sadě Visual Studio 2015 a novějších verzích).

  • Přístupnost pásu karet MFC byla změněna. Místo jednoúrovňové architektury je teď hierarchická architektura. Staré chování můžete stále používat voláním CRibbonBar::EnableSingleLevelAccessibilityMode().

  • CDatabase::GetConnect metoda je odebrána. Aby se zlepšilo zabezpečení, připojovací řetězec se teď ukládá zašifrovaný a dešifruje se jen podle potřeby; nelze ho vrátit jako prostý text. Řetězec lze získat pomocí CDatabase::Dump metody.

  • CWnd::OnPowerBroadcast Podpis byl změněn. Definice tohoto zpracovatele zpráv byla změněna tak, aby přijal LPARAM jako druhý parametr.

  • Podpisy jsou změněny, aby vyhovovaly zpracovatelům zpráv. Seznamy parametrů u následujících funkcí se změnily a používají nově přidané popisovače zpráv ON_WM_ *:

    • CWnd::OnDisplayChange změněno na (UINT, int, int) místo (WPARAM, LPARAM), aby bylo možné nové makro ON_WM_DISPLAYCHANGE použít v mapě zpráv.

    • CFrameWnd::OnDDEInitiate byl změněn z (WPARAM, LPARAM) na (CWnd*, UINT, UINT), aby bylo možné v mapě zpráv použít nové makro ON_WM_DDE_INITIATE.

    • CFrameWnd::OnDDEExecute byla změněna z (WPARAM, LPARAM) na (CWnd*, HANDLE), aby bylo možné v mapě zpráv používat nové makro ON_WM_DDE_EXECUTE.

    • CFrameWnd::OnDDETerminate bylo změněno na parametr typu (CWnd*) místo (WPARAM, LPARAM), aby bylo možné v mapě zpráv použít nové makro ON_WM_DDE_TERMINATE.

    • CMFCMaskedEdit::OnCut změna na žádné parametry místo (WPARAM, LPARAM), aby bylo možné nové ON_WM_CUT makro použít v mapě zpráv.

    • CMFCMaskedEdit::OnClear změna na žádné parametry místo (WPARAM, LPARAM), aby bylo možné nové ON_WM_CLEAR makro použít v mapě zpráv.

    • CMFCMaskedEdit::OnPaste změněno na žádné parametry namísto (WPARAM, LPARAM), aby mohlo být nové makro ON_WM_PASTE použito v mapě zpráv.

  • #ifdef direktivy v souborech hlaviček MFC jsou odebrány. V souborech hlaviček MFC souvisejících s nepodporovanými verzemi systému Windows (#ifdef) jsou odebrány různé WINVER < 0x0501 direktivy.

  • Knihovna DLL ATL (atl120.dll) se odebere. Knihovna ATL je nyní poskytována jako záhlaví a statická knihovna (atls.lib).

  • Atlsd.lib, atlsn.lib a atlsnd.lib jsou odebrány. Knihovna Atls.lib již nemá závislosti na znakové sadě ani kód specifický pro ladění/vydání. Protože princip funkce je stejný pro Unicode/ANSI i ladění/vydání, je vyžadována pouze jedna verze knihovny.

  • Nástroj ATL/MFC Trace je odstraněn společně s ATL DLL a mechanismus trasování byl zjednodušen. Konstruktor CTraceCategory nyní přijímá jeden parametr (název kategorie) a makra TRACE volají funkce pro ladicí sestavy CRT.

Zásadní změny sady Visual Studio 2012

kompilátor

  • Možnost kompilátoru /Yl se změnila. Kompilátor ve výchozím nastavení používá tuto možnost, což může vést k LNK2011 chybám za určitých podmínek. Další informace naleznete v tématu /Yl (vložení odkazu PCH pro knihovnu ladění).

  • V kódu, který je zkompilován pomocí /clr, klíčové slovo 'class' definuje výčet C++11, a nikoli výčet CLR (Common Language Runtime). Pokud chcete definovat výčet CLR, musíte mít explicitní informace o jeho přístupnosti.

  • Pomocí klíčového slova šablona můžete explicitně vyřešit nejednoznačnost závislého názvu (shoda se standardem jazyka C++). V následujícím příkladu je zvýrazněné klíčové slovo šablony povinné k vyřešení nejednoznačnosti. Další informace naleznete v tématu Rozlišení názvů pro závislé typy.

    template < typename X = "", typename = "" AY = "">
    struct Container { typedef typename AY::template Rebind< X> ::Other AX; };
    
  • Konstantní výraz typu float již není povolen jako argument šablony, jak je znázorněno v následujícím příkladu.

    template<float n=3.14>
    struct B {};  // error C2993: 'float': illegal type for non-type template parameter 'n'
    
  • Kód, který je zkompilovaný pomocí možnosti příkazového řádku /GS a který má chybu mimo rozsah o jednu položku, může vést k ukončení procesu během spouštění, jak je znázorněno v následujícím příkladu pseudokódu.

    char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminate
    
  • Výchozí architektura sestavení x86 byla změněna na SSE2; kompilátor proto může generovat instrukce SSE a použije registry XMM k provádění výpočtů s plovoucí desetinou čárkou. Pokud se chcete vrátit k předchozímu chování, použijte příznak kompilátoru /arch:IA32 k určení architektury jako IA32.

  • Kompilátor může vydávat upozornění Upozornění kompilátoru (úroveň 4) C4703 a C4701 v případech, kde dříve nebyla vydávána. Kompilátor používá silnější kontroly použití neinicializovaných místních proměnných typu ukazatele.

  • Pokud je zadán nový příznak /HIGHENTROPYVA linkeru, Systém Windows 8 obvykle způsobí, že přidělení paměti vrátí 64bitovou adresu. (Před Windows 8 taková přidělení obvykle vracela adresy, které byly menší než 2 GB.) Tato změna může odhalit chyby související se zkracováním ukazatelů v existujícím kódu. Ve výchozím nastavení je tento přepínač zapnutý. Chcete-li toto chování zakázat, zadejte /HIGHENTROPYVA:NO.

  • Spravovaný kompilátor (Visual Basic/C#) také podporuje spravované kompilace /HIGHENTROPYVA. V tomto případě /HIGHENTROPYVAswitch je ale ve výchozím nastavení vypnutý.

integrované vývojové prostředí (IDE)

  • Přestože doporučujeme nevytvářet aplikace Windows Forms v C++/CLI, je podporována údržba stávajících aplikací s uživatelským rozhraním C++/CLI. Pokud potřebujete vytvořit aplikaci pro Windows Forms nebo jinou .NET UI aplikaci, použijte C# nebo Visual Basic. Pro účely interoperability používejte pouze C++/CLI.

Knihovna paralelních vzorů a knihovna Concurrency Runtime

Výčet SchedulerTypeUmsThreadDefault je zastaralý. Specifikace UmsThreadDefault vyvolává upozornění na zastaralost a interně mapuje zpět na ThreadScheduler.

Standardní knihovna

  • Po zásadní změně mezi standardy C++98/03 a C++11, používání explicitních argumentů šablon pro volání make_pair()—tak jako v make_pair<int, int>(x, y)—se obvykle nedaří zkompilovat v rámci Visual C++ v prostředí Visual Studio 2012. Řešením je vždy volat make_pair() bez explicitních argumentů šablony – jako v make_pair(x, y). Poskytnutí explicitních argumentů šablony popírá účel funkce. Pokud požadujete přesnou kontrolu nad výsledným typem, použijte pair místo make_pair - jako v pair<short, short>(int1, int2).

  • Další zásadní změna mezi standardy C++98/03 a C++11: Pokud je A implicitně konvertibilní na B a B je implicitně konvertibilní na C, ale A není implicitně konvertibilní na C, C++98/03 a Visual Studio 2010 umožňovaly pair<A, X> převést (implicitně nebo explicitně) na pair<C, X>. (Druhý typ X, tady není zajímavý a není specifický pro první typ v páru.) Kompilátor C++ v sadě Visual Studio 2012 zjistí, že A není implicitně převoditelný na jazyk C, a odebere převod páru z rozlišení přetížení. Tato změna je pro mnoho scénářů pozitivní. Například přetížení func(const pair<int, int>&) a func(const pair<string, string>&), a volání func() s pair<const char *, const char *> se zkompiluje s touto změnou. Tato změna však přeruší kód, který se spoléhal na agresivní převody párů. Takový kód lze obvykle opravit provedením jedné části převodu explicitně – například předáním make_pair(static_cast<B>(a), x) funkce, která očekává pair<C, X>.

  • Variadické šablony simulované ve Visual Studio 2010, jako je make_shared<T>(arg1, arg2, argN), až do limitu 10 argumentů, generováním přetížení a specializací pomocí preprocesorových mechanismů. V sadě Visual Studio 2012 je tento limit omezen na pět argumentů, aby se zlepšila doba kompilace a spotřeba paměti kompilátoru pro většinu uživatelů. Předchozí limit ale můžete nastavit explicitním definováním _VARIADIC_MAX jako 10 na úrovni projektu.

  • C++11 17.6.4.3.1 [macro.names]/2 zakazuje nahrazení klíčových slov makry při zahrnutí hlaviček standardní knihovny C++. Hlavičky teď generují chyby kompilátoru, pokud detekují klíčová slova nahrazená makrem. (Definování _ALLOW_KEYWORD_MACROS umožňuje kompilaci takového kódu, ale důrazně nedoporučujeme toto použití.) Jako výjimka je ve výchozím nastavení povolena forma new makra, protože hlavičky se komplexně chrání pomocí#pragma push_macro("new")/#undef new/#pragma pop_macro("new") . Definování _ENFORCE_BAN_OF_MACRO_NEW dělá přesně to, co jeho název napovídá.

  • Pokud chcete implementovat různé optimalizace a kontroly ladění, implementace standardní knihovny C++ záměrně přeruší binární kompatibilitu mezi verzemi sady Visual Studio (2005, 2008, 2010, 2012). Pokud se používá standardní knihovna C++, zakáže kombinování souborů objektů a statických knihoven kompilovaných pomocí různých verzí do jednoho binárního souboru (EXE nebo DLL) a zakáže předávání objektů standardní knihovny jazyka C++ mezi binárními soubory kompilovanými pomocí různých verzí. Kombinace souborů objektů a statických knihoven (pomocí standardní knihovny jazyka C++, která byla zkompilována pomocí sady Visual Studio 2010 s knihovnami, které byly zkompilovány pomocí kompilátoru jazyka C++ v sadě Visual Studio 2012, generuje chyby linkeru o neshodě _MSC_VER, kde _MSC_VER je makro obsahující hlavní verzi kompilátoru (1700 pro Visual C++ v sadě Visual Studio 2012). Tato kontrola nedokáže rozpoznat kombinování knihoven DLL a nedokáže rozpoznat kombinování, které zahrnuje Visual Studio 2008 nebo starší.

  • Kromě zjišťování neshod _ITERATOR_DEBUG_LEVEL, které byly implementovány v sadě Visual Studio 2010, kompilátor jazyka C++ v sadě Visual Studio 2012 detekuje neshody knihoven runtime. K těmto neshodám dochází, když jsou možnosti kompilátoru /MT (statická verze), /MTd (statické ladění), /MD (dynamická verze) a /MDd (dynamické ladění) smíšené.

  • operator<(), , operator>()operator<=()a operator>=() byly dříve k dispozici pro std::unordered_map a stdext::hash_map rodiny kontejnerů, i když jejich implementace nebyly užitečné. Tyto nestandardní operátory byly ve Visual C++ ve Visual Studio 2012 odebrány. Kromě toho byla implementace operator==() a operator!=() pro std::unordered_map rodinu rozšířena tak, aby pokrývala stdext::hash_map rodinu. (Doporučujeme, abyste se vyhnuli použití stdext::hash_map rodiny v novém kódu.)

  • C++11 22.4.1.4 [locale.codecvt] určuje, že codecvt::length() a codecvt::do_length() by měly přijímat upravitelné parametry stateT&, ale Visual Studio 2010 používalo const stateT&. Kompilátor jazyka C++ v sadě Visual Studio 2012 přebírá stateT& podle mandátu standardu. Tento rozdíl je významný pro každého, kdo se pokouší přepsat virtuální funkci do_length().

CRT

  • Halda C Runtime (CRT), která se používá pro operátor new a funkci malloc(), už není vyhrazená. CRT teď používá haldu procesu. To znamená, že halda není zničena při uvolnění knihovny DLL, takže knihovny DLL, které jsou staticky propojené s CRT, musí zajistit, aby paměť přidělená kódem knihovny DLL byla vyčištěna před jejím uvolněním.

  • Funkce iscsymf() se používá se zápornými hodnotami.

  • Struktura threadlocaleinfostruct se změnila tak, aby vyhovovala změnám funkcí národního prostředí.

  • Funkce CRT, které mají odpovídající vnitřní funkce, jako memxxx(), strxxx(), jsou odebrány z intrin.h. Pokud jste intrin.h zahrnuli pouze pro tyto funkce, musíte nyní zahrnout odpovídající hlavičky CRT.

MFC a ATL

  • Odebrána podpora Fusion (afxcomctl32.h); takže byly odebrány všechny metody, které jsou definovány v <afxcomctl32.h>. Soubory <afxcomctl32.h> hlaviček a <afxcomctl32.inl> byly odstraněny.

  • Změnil se název CDockablePane::RemoveFromDefaultPaneDividier na CDockablePane::RemoveFromDefaultPaneDivider.

  • Změnil se podpis CFileDialog::SetDefExt pro použití LPCTSTR, a proto jsou tím ovlivněny buildy Unicode.

  • Odebrání zastaralých kategorií trasování ATL

  • Změna podpisu CBasePane::MoveWindow tak, aby přijal const CRect.

  • Změnil se podpis CMFCEditBrowseCtrl::EnableBrowseButton.

  • Byly odebrány vlastnosti m_fntTabs a m_fntTabsBold ze třídy CMFCBaseTabCtrl.

  • Byl přidán parametr CMFCRibbonStatusBarPane do konstruktorů. (Jedná se o výchozí parametr, a proto neporušuje zdrojový kód.)

  • Přidání parametru do konstruktoru CMFCRibbonCommandsListBox (Jedná se o výchozí parametr, a proto nenarušuje zdroj.)

  • Jsme odebrali rozhraní API AFXTrackMouse (a související zpracování časovače). Místo toho použijte rozhraní API Win32 TrackMouseEvent .

  • Přidání parametru do konstruktoru CFolderPickerDialog (Jedná se o výchozí parametr, a proto neporušuje zdroj.)

  • CFileStatus změna velikosti struktury: Člen m_attribute se změnil z BYTE na DWORD (aby odpovídal hodnotě vrácené z GetFileAttributes).

  • CRichEditCtrl a CRichEditView v buildech Unicode používejte MSFTEDIT_CLASS (ovládací prvek RichEdit 4.1) místo RICHEDIT_CLASS (ovládací prvek RichEdit 3.0).

  • Odebráno AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground, protože je ve Windows Vista, Windows 7 a Windows 8 vždy PRAVDA.

  • Odebráno AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable, protože je vždy TRUE na Windows Vista, Windows 7 a Windows 8.

  • Bylo odebráno AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea. Volání rozhraní API systému Windows přímo ve Windows Vista, Windows 7 a Windows 8.

  • Odstraněno AFX_GLOBAL_DATA::DwmDefWindowProc. Volání rozhraní API systému Windows přímo ve Windows Vista, Windows 7 a Windows 8.

  • Přejmenováno AFX_GLOBAL_DATA::DwmIsCompositionEnabled na IsDwmCompositionEnabled, aby se vyloučila kolize názvů.

  • Změněné identifikátory pro řadu interních časovačů MFC a přesunuté definice do afxres.h (AFX_TIMER_ID_*).

  • Změnil jsem podpis metody OnExitSizeMove tak, aby odpovídal makru ON_WM_EXITSIZEMOVE:

    • CFrameWndEx

    • CMDIFrameWndEx

    • CPaneFrameWnd

  • Změnil se název a podpis OnDWMCompositionChanged tak, aby souhlasil s makrem ON_WM_DWMCOMPOSITIONCHANGED:

    • CFrameWndEx

    • CMDIFrameWndEx

    • CPaneFrameWnd

  • Změna podpisu OnMouseLeave metody tak, aby souhlasila s makrem ON_WM_MOUSELEAVE:

    • CMFCCaptionBar

    • CMFCColorBar

    • CMFCHeaderCtrl

    • CMFCProperySheetListBox

    • CMFCRibbonBar

    • CMFCRibbonPanelMenuBar

    • CMFCRibbonRichEditCtrl

    • CMFCSpinButtonCtrl

    • CMFCToolBar NahraditTentoText

    • CMFCToolBarComboBoxEdit

    • CMFCToolBarEditCtrl

    • CMFCAutoHideBar

  • Změna podpisu OnPowerBroadcast tak, aby odpovídal makru ON_WM_POWERBROADCAST:

    • CFrameWndEx

    • CMDIFrameWndEx

  • Změnil se podpis OnStyleChanged, aby odpovídal makru ON_WM_STYLECHANGED:

    • CMFCListCtrl

    • CMFCStatusBar

  • Přejmenování interní metody FontFamalyProcFonts na FontFamilyProcFonts.

  • Odebrali jsme mnoho globálních statických CString objektů, abychom v některých situacích odstranili úniky paměti (nahrazeno #definy), a také následující členské proměnné třídy:

    • CKeyBoardManager::m_strDelimiter

    • CMFCPropertyGridProperty::m_strFormatChar

    • CMFCPropertyGridProperty::m_strFormatShort

    • CMFCPropertyGridProperty::m_strFormatLong

    • CMFCPropertyGridProperty::m_strFormatUShort

    • CMFCPropertyGridProperty::m_strFormatULong

    • CMFCPropertyGridProperty::m_strFormatFloat

    • CMFCPropertyGridProperty::m_strFormatDouble

    • CMFCToolBarImages::m_strPngResType

    • CMFCPropertyGridProperty::m_strFormat

  • Změnil se podpis CKeyboardManager::ShowAllAccelerators a byl odstraněn parametr oddělovače akcelerátoru.

  • Přidána CPropertyPage::GetParentSheet, a ve třídě CPropertyPage zavolat ji namísto volání GetParent pro získání správného rodičovského okna listu, které může být nadřazené nebo prarodičovské okno CPropertyPage. Možná budete muset změnit kód tak, aby volal GetParentSheet místo GetParent.

  • Opravili jsme nevyvážené #pragma warning(push) v ATLBASE.H, což způsobovalo nesprávné zakázání upozornění. Tato upozornění jsou nyní správně povolená po zpracování ATLBASE.H.

  • Přesunuté metody související s D2D z AFX_GLOBAL_DATA do _AFX_D2D_STATE:

    • GetDirectD2dFactory

    • GetWriteFactory

    • GetWICFactory

    • InitD2D

    • ReleaseD2DRefs

    • IsD2DInitialized

    • D2D1MakeRotateMatrix

    • Místo toho, abyste například zavolali afxGlobalData.IsD2DInitialized, zavolejte AfxGetD2DState->IsD2DInitialized.

  • Byly odstraněny zastaralé soubory ATL*.CPP ze složky \atlmfc\include\.

  • Inicializace afxGlobalData je nyní prováděna na vyžádání namísto v čase inicializace CRT, aby splňovala požadavky DLLMain.

  • Do třídy CMFCOutlookBarPane byla přidána metoda RemoveButtonByIndex.

  • Opraveno CMFCCmdUsageCount::IsFreqeuntlyUsedCmd na IsFrequentlyUsedCmd.

  • Opravili jsme několik výskytů RestoreOriginalstate na RestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).

  • Odebrané nepoužité metody z CDockablePane: SetCaptionStyle, IsDrawCaption, IsHideDisabledButtons, GetRecentSiblingPaneInfo, a CanAdjustLayout.

  • Byly odstraněny CDockablePane statické členské proměnné m_bCaptionText a m_bHideDisabledButtons.

  • Byla přidána metoda přetížení DeleteString do CMFCFontComboBox.

  • Odebrané nepoužívané metody z CPane: GetMinLength a IsLastPaneOnLastRow.

  • Přejmenováno CPane::GetDockSiteRow(CDockingPanesRow *) na CPane::SetDockSiteRow.

Zásadní změny sady Visual Studio 2010

kompilátor

  • Klíčové auto 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ěna.

  • static_assert Nové klíčové slovo je zavedeno, což způsobí konflikt názvů, pokud v kódu již existuje identifikátor podle daného názvu.

  • Podpora nového zápisu lambda vylučuje možnost kódování necitovaného identifikátoru GUID v atributu uuid IDL.

  • Rozhraní .NET Framework 4 zavádí koncept poškozených výjimek stavu, což jsou výjimky, které zanechávají proces ve stavu, který nelze opravit. Ve výchozím nastavení nelze zachytit výjimku poškozeného stavu ani s možností kompilátoru /EHa, která zachytí všechny ostatní výjimky. Pokud chcete explicitně zachytit výjimku poškozeného stavu, použijte příkazy __try-__except. Nebo použijte atribut [HandledProcessCorruptedStateExceptions], který funkci umožní zachytit výjimky poškozeného stavu. Tato změna má vliv především na programátory systému, kteří mohou muset zachytit výjimku poškozeného stavu. Osm výjimek jsou STATUS_ACCESS_VIOLATION, STATUS_STACK_OVERFLOW, EXCEPTION_ILLEGAL_INSTRUCTION, EXCEPTION_IN_PAGE_ERROR, EXCEPTION_INVALID_DISPOSITION, EXCEPTION_NONCONTINUABLE_EXCEPTION, EXCEPTION_PRIV_INSTRUCTION, STATUS_UNWIND_CONSOLIDATE. Další informace o těchto výjimkách naleznete v makre GetExceptionCode .

  • Revidovaná /GS možnost kompilátoru chrání před přetečením vyrovnávací paměti komplexněji než v předchozích verzích. Tato verze může vložit další kontroly zabezpečení do softwarového zásobníku, které můžou snížit výkon. Pomocí nového __declspec(safebuffers) klíčového slova instruujte kompilátoru, aby nevkládaly kontroly zabezpečení pro konkrétní funkci.

  • Pokud kompilujete s možnostmi /GL (Optimalizace celého programu) a /clr (kompilace Common Language Runtime), bude možnost /GL ignorována. Tato změna byla provedena, protože kombinace možností kompilátoru poskytovala malou výhodu. Vzhledem k této změně se zlepšil výkon sestavení.

  • Ve výchozím nastavení je podpora trigrafů v sadě Visual Studio 2010 zakázaná. Pomocí možnosti kompilátoru /Zc:trigraphs povolte podporu trigrafů. Trigraf se skládá ze dvou po sobě jdoucích otazník (??") následovaných jedinečným třetím znakem. Kompilátor nahradí trigraf odpovídajícím interpunkčním znakem. Kompilátor například nahradí ??= trigraf znakem #. Ve zdrojových souborech jazyka C použijte trigrafy, pokud používají znakové sady, které neobsahují vhodné grafické reprezentace pro některé interpunkční znaky.

  • Linker už nepodporuje optimalizaci pro Windows 98. Možnost /OPT (Optimalizace) vytvoří chybu v době kompilace, pokud zadáte /OPT:WIN98 nebo /OPT:NOWIN98.

  • Byly změněny výchozí možnosti kompilátoru určené vlastnostmi systému sestavení RuntimeLibrary a DebugInformationFormat. Ve výchozím nastavení jsou tyto vlastnosti sestavení zadány v projektech vytvořených verzí visual C++ 7.0 až 10.0. Pokud migrujete projekt vytvořený visual C++ 6.0, zvažte, zda chcete zadat hodnotu pro tyto vlastnosti.

  • V aplikaci Visual Studio 2010, RuntimeLibrary = MultiThreaded (/MD) a DebugInformationFormat = ProgramDatabase (/Zi). Ve Visual C++ 9.0, RuntimeLibrary = MultiThreaded (/MT) a DebugInformationFormat = Disabled.

CLR

  • Kompilátory Microsoft C# a Visual Basic nyní mohou vytvářet sestavení bez primární interoperační sestavy (no-PIA). Sestavení bez PIA může používat COM typy i bez nasazení příslušného primárního sestavení pro spolupráci (PIA). Při využívání sestavení bez PIA vytvořených pomocí jazyka Visual C# nebo Visual Basic je nutné na příkazovém řádku kompilace nejprve odkázat na sestavení PIA, a teprve potom na jakékoli sestavení no-PIA, které používá danou knihovnu.

Projekty jazyka C++ sady Visual Studio a MSBuild

  • Projekty visual Studio C++ jsou teď založené na nástroji MSBuild. Soubory projektu proto používají nový formát souboru XML a příponu souboru .vcxproj. Visual Studio 2010 automaticky převede soubory projektu ze starších verzí sady Visual Studio do nového formátu souborů. Existující projekt je ovlivněn, pokud závisí na předchozím nástroji sestavení, VCBUILD.exe, nebo příponě souboru projektu .vcproj.

  • V dřívějších verzích podporuje Visual C++ pozdní vyhodnocení seznamů vlastností. Například nadřazený seznam vlastností může importovat podřízený seznam vlastností a nadřazený může použít proměnnou definovanou v podřízeném k definování dalších proměnných. Pozdní vyhodnocení dovolilo rodiči používat dětskou proměnnou i před importem vlastnostního listu dítěte. V sadě Visual Studio 2010 nelze proměnnou listu projektu použít dříve, než je definována, protože nástroj MSBuild podporuje pouze předčasné vyhodnocení.

integrované vývojové prostředí (IDE)

  • Dialogové okno ukončení aplikace už aplikaci neskoncuje. V předchozích verzích se při abort()terminate() zavření maloobchodního sestavení aplikace v knihovně C Run-Time zobrazila zpráva ukončení aplikace v okně konzoly nebo dialogovém okně. Zpráva částečně řekla: "Tato aplikace požádala Runtime, aby jej ukončil neobvyklým způsobem. Další informace vám poskytne tým podpory aplikace. Zpráva o ukončení aplikace byla redundantní, protože systém Windows následně zobrazil aktuální obslužnou rutinu ukončení, což byla obvykle dialogové okno Zasílání zpráv o chybách systému Windows (Dr. Watson) nebo ladicí program sady Visual Studio. Počínaje sadou Visual Studio 2010 se zpráva nezobrazuje v knihovně runtime jazyka C. Modul runtime navíc brání ukončení aplikace před spuštěním ladicího programu. Jedná se o zásadní změnu pouze v případě, že závisíte na předchozím chování zprávy o ukončení aplikace.

  • Technologie IntelliSense konkrétně pro Visual Studio 2010 nefunguje pro kód nebo atributy C++/CLI, funkce Najít všechny odkazy nefunguje pro místní proměnné a model kódu nenačítá názvy typů z importovaných sestavení nebo překládá typy na plně kvalifikované názvy.

Knihovny

  • Třída SafeInt je součástí jazyka Visual C++ a již není součástí samostatného stahování. Jedná se o zásadní změnu pouze v případě, že jste vyvinuli třídu, kterou jste pojmenovali "SafeInt".

  • Model nasazení knihoven už nepoužívá manifesty k vyhledání konkrétní verze dynamické knihovny odkazů. Místo toho název každé dynamické knihovny odkazů obsahuje její číslo verze a tento název použijete k vyhledání knihovny.

  • V předchozích verzích sady Visual Studio jste mohli znovu sestavit knihovny runtime. Visual Studio 2010 už nepodporuje vytváření vlastních kopií souborů knihovny runtime jazyka C.

Standardní knihovna

  • Hlavička <iterator> už není zahrnuta automaticky mnoha dalšími soubory hlaviček. Místo toho tuto hlavičku explicitně zahrňte, pokud potřebujete podporu samostatných iterátorů definovaných v hlavičce. Existující projekt je ovlivněn, pokud závisí na předchozím nástroji sestavení, VCBUILD.exe, nebo příponě souboru projektu .vcproj.iterator.

  • V záhlaví <algorithm> jsou odstraněny funkce checked_* a unchecked_*. A v <iterator>> záhlaví byla checked_iterator třída odstraněna a unchecked_array_iterator třída byla přidána.

  • Konstruktor CComPtr::CComPtr(int) je odebrán. Tento konstruktor umožnil vytvoření objektu CComPtr z makra NULL, ale byl nepotřebný a umožňoval nesmyslné konstrukce z nenulových celých čísel.

    Hodnota A CComPtr je stále možné vytvořit z hodnoty NULL, která je definována jako 0, ale pokud se vytvoří z jiného čísla než literál 0, selže. Místo toho použijte nullptr.

  • Byly odebrány následující ctype členské funkce: ctype::_Do_narrow_s, ctype::_Do_widen_s, ctype::_narrow_s, ctype::_widen_s. Pokud aplikace používá některou z těchto členských funkcí, musíte ji nahradit odpovídající nezabezpečenou verzí: ctype::do_narrow, ctype::do_widen, ctype::narrow. ctype::widen

Knihovny CRT, MFC a ATL

  • Uživatelům byla odebrána podpora pro vytváření knihoven CRT, MFC a ATL. Například není k dispozici žádný vhodný soubor NMAKE. Uživatelé ale stále mají přístup ke zdrojovému kódu těchto knihoven. A dokument, který popisuje možnosti nástroje MSBuild, které Microsoft používá k sestavení těchto knihoven, bude pravděpodobně publikován v blogu týmu Visual C++.

  • Podpora MFC pro IA64 byla odebrána. Podpora CRT a ATL v IA64 je však stále k dispozici.

  • Ordnály se již znovu nepoužívají v souborech definice modulu MFC (.def). Tato změna znamená, že se ordinaly nebudou lišit mezi minor verzemi a binární kompatibilita pro aktualizace Service Pack a implementace rychlých oprav bude vylepšena.

  • Do CDocTemplate třídy byla přidána nová virtuální funkce. Tato nová virtuální funkce je CDocTemplate třída. Předchozí verze OpenDocumentFile měla dva parametry. Nová verze má tři parametry. Pro podporu správce restartování musí každá třída odvozená z CDocTemplate implementovat verzi, která má tři parametry. Nový parametr je bAddToMRU.

Makra a proměnné prostředí

  • Proměnná prostředí __MSVCRT_HEAP_SELECT se už nepodporuje. Proměnná prostředí byla odstraněna a není za ni žádná náhrada.

Microsoft Macro Assembler – referenční dokumentace

  • Z referenčního kompilátoru Microsoft Macro Assembler bylo odebráno několik direktiv. Odebrané direktivy jsou .186, .286, .286P, .287, .8086, .8087 a .NO87.

Zásadní změny sady Visual Studio 2008

kompilátor

  • Platformy Windows 95, Windows 98, Windows ME a systém Windows NT se už nepodporují. Tyto operační systémy byly odebrány ze seznamu cílových platforem.

  • Kompilátor již nepodporuje více atributů, které byly přímo přidružené k ATL Serveru. Následující atributy se už nepodporují:

    • perf_counter

    • perf_objekt

    • perfmon

    • zpracovatel požadavků

    • zpracovatel SOAP

    • SOAP záhlaví

    • soap_method (metoda SOAP)

    • název_štítku

Projekty Visual Studio C++

  • Při upgradu projektů z předchozích verzí sady Visual Studio možná budete muset upravit makra WINVER a _WIN32_WINNT tak, aby byla větší nebo rovna 0x0500.

  • Počínaje sadou Visual Studio 2008 nemá průvodce novým projektem možnost vytvořit projekt SQL Serveru C++. Projekty SQL Serveru vytvořené pomocí starší verze sady Visual Studio budou stále kompilovat a fungovat správně.

  • Soubor hlaviček rozhraní WINDOWS API Winable.h byl odebrán. Místo toho zahrňte Winuser.h.

  • Knihovna rozhraní Windows API Rpcndr.lib byla odebrána. Odkazujte místo toho pomocí rpcrt4.lib.

CRT

  • Byla odebrána podpora pro Windows 95, Windows 98, Windows Millennium Edition a systém Windows NT 4.0.

  • Byly odebrány následující globální proměnné:

    • _osplatform

    • _osver

    • _winmajor

    • _winminor

    • _winver

  • Následující funkce byly odebrány. Použijte funkce GetVersion rozhraní WINDOWS API nebo GetVersionEx místo toho:

    • _get_osplatform

    • _get_osver

    • _get_winmajor

    • _get_winminor

    • _get_winver

  • Syntaxe poznámek SAL se změnila. Další informace najdete v tématu Poznámky SAL.

  • Filtr IEEE teď podporuje instrukční sadu SSE 4.1. Další informace najdete v tématu _fpieee_flt.

  • Knihovny runtime jazyka C, které jsou dodávány se sadou Visual Studio, již nejsou závislé na systémové knihovně DLL msvcrt.dll.

Standardní knihovna

  • Byla odebrána podpora pro Windows 95, Windows 98, Windows Millennium Edition a systém Windows NT 4.0.

  • Při kompilaci v režimu ladění s definovaným _HAS_ITERATOR_DEBUGGING (nahrazeno _ITERATOR_DEBUG_LEVEL po sadě Visual Studio 2010) aplikace nyní vyvolá výjimku, když se iterátor pokusí inkrementovat nebo dekrementovat přes hranice podkladového kontejneru.

  • Členová proměnná c třídy Stack je nyní deklarována chráněná. Dříve byla tato členová proměnná deklarována jako veřejná.

  • Chování money_get::do_get se změnilo. Dříve, při analýze peněžní částky s více desetinnými místy, než požaduje frac_digits, do_get je všechny spotřebovávala. do_get Teď po použití většiny frac_digits znaků přestane parsovat.

knihovna ATL

  • AtL nejde sestavit bez závislosti na CRT. V dřívějších verzích sady Visual Studio můžete pomocí #define ATL_MIN_CRT vytvořit projekt ATL minimálně závislý na CRT. V sadě Visual Studio 2008 jsou všechny projekty ATL minimálně závislé na CRT bez ohledu na to, jestli je definován ATL_MIN_CRT.

  • Základ kódu ATL Serveru byl vydán jako sdílený zdrojový projekt v CodePlexu a není nainstalován jako součást sady Visual Studio. Třídy pro kódování a dekódování dat z atlenc.h a užitkové funkce a třídy z atlutil.h a atlpath.h byly zachovány a jsou nyní součástí knihovny ATL. Několik souborů přidružených k ATL Serveru již není součástí sady Visual Studio.

  • Některé funkce už nejsou součástí knihovny DLL. Jsou stále umístěné v importní knihovně. To neovlivní kód, který staticky používá funkce. Ovlivní pouze kód, který tyto funkce používá dynamicky.

  • Makra PROP_ENTRY a PROP_ENTRY_EX jsou zastaralá a nahrazena makry PROP_ENTRY_TYPE a PROP_ENTRY_TYPE_EX z bezpečnostních důvodů.

Sdílené třídy ATL/MFC

  • AtL nejde sestavit bez závislosti na CRT. V dřívějších verzích sady Visual Studio jste mohli použít #define ATL_MIN_CRT, aby projekt ATL byl minimálně závislý na CRT. V sadě Visual Studio 2008 jsou všechny projekty ATL minimálně závislé na CRT bez ohledu na to, jestli je definován ATL_MIN_CRT.

  • Základ kódu ATL Serveru byl vydán jako sdílený zdrojový projekt v CodePlexu a není nainstalován jako součást sady Visual Studio. Třídy pro kódování a dekódování dat z atlenc.h a užitkové funkce a třídy z atlutil.h a atlpath.h byly zachovány a jsou nyní součástí knihovny ATL. Několik souborů přidružených k ATL Serveru již není součástí sady Visual Studio.

  • Některé funkce už nejsou součástí knihovny DLL. Jsou stále umístěné v importní knihovně. To neovlivní kód, který staticky používá funkce. Ovlivní pouze kód, který tyto funkce používá dynamicky.

knihovna MFC

  • CTime Třída: Třída CTime nyní přijímá kalendářní data od 1. 1. 1900 C.E. namísto 1.1.1970 C.E.

  • Pořadí ovládacích prvků v dialogových oknech MFC: Správné pořadí více prvků v dialogovém okně MFC je narušeno, pokud je do pořadí vložen ActiveX ovládací prvek MFC. Tato změna tento problém opraví.

    Můžete například vytvořit aplikaci dialogového okna MFC, která má ovládací prvek ActiveX a několik ovládacích prvků pro úpravy. Umístěte ovládací prvek ActiveX doprostřed pořadí ovládacích prvků pro úpravy. Spusťte aplikaci, klikněte na ovládací prvek pro úpravy, jehož pořadí ovládacích prvků je za ovládacím prvku ActiveX, a potom na kartu. Před touto změnou se fokus dostal na ovládací prvek pro úpravy, který následuje za ovládacím prvku ActiveX, a ne na další ovládací prvek pro úpravy v pořadí ovládacích prvků.

  • CFileDialog Třída: Vlastní šablony pro CFileDialog třídu nelze automaticky přenést do systému Windows Vista. Jsou stále použitelné, ale nebudou mít další funkce nebo vzhled dialogových oken windows Vista.

  • CWnd Třída a CFrameWnd třída: Metoda CWnd::GetMenuBarInfo byla odebrána.

    Tato CFrameWnd::GetMenuBarInfo metoda je nyní ne virtuální metodou. Další informace naleznete v tématu funkce GetMenuBarInfo v sadě Windows SDK.

  • Podpora ROZHRANÍ MFC ISAPI: MFC už nepodporuje vytváření aplikací pomocí rozhraní ISAPI (Internet Server Application Programming Interface). Pokud chcete vytvořit aplikaci ISAPI, použijte rozšíření ISAPI přímo.

  • Zastaralá rozhraní API ANSI: Verze ANSI několika metod MFC jsou zastaralé. V budoucích aplikacích používejte verze unicode těchto metod. Další informace naleznete v tématu Požadavky na sestavení pro Windows Vista Běžné ovládací prvky.

Zásadní změny sady Visual Studio 2005

CRT

  • Řada funkcí je zastaralá. Viz zastaralé funkce CRT.

  • Mnoho funkcí teď ověřuje jejich parametry a zastaví provádění, pokud jsou zadané neplatné parametry. Toto ověření může přerušit kód, který předává neplatné parametry, a spoléhá na to, že je funkce ignoruje nebo pouze vrací kód chyby. Viz ověření parametru.

  • Hodnota popisovače souboru -2 se teď používá k označení, že stdout a stderr nejsou dostupné pro výstup, například v aplikaci pro Windows, která nemá okno konzoly. Použitá předchozí hodnota byla -1. Další informace najdete v tématu _fileno.

  • Knihovny CRT pro jedno vlákno (libc.lib a libcd.lib) byly odebrány. Použijte vícevláknové knihovny CRT. Příznak kompilátoru /ML se už nepodporuje. V případech, kdy je rozdíl mezi vícevláknovým kódem a kódem s jedním vláknem potenciálně významný, byly přidány neblokované verze některých funkcí.

  • Přetížení pow, double pow(int, int), bylo odstraněno, aby lépe odpovídalo standardu.

  • Specifikátor formátu %n už není ve výchozím nastavení podporován v žádné skupině funkcí printf, protože je ze své podstaty nezabezpečený. Pokud je zjištěna hodnota %n, výchozím chováním je vyvolání neplatné obslužné rutiny parametru. Pro povolení %n podpory použijte _set_printf_count_output (viz také _get_printf_count_output).

  • sprintf Nyní vytiskne záporné znaménko u nuly s nulovým znaménkem.

  • swprintf byla změněna tak, aby odpovídala standardu; teď vyžaduje parametr velikosti. Formulář bez parametru swprintf velikosti je zastaralý.

  • _set_security_error_handler bylo odebráno. Odeberte všechna volání této funkce; Výchozí obslužná rutina je mnohem bezpečnější způsob řešení chyb zabezpečení.

  • time_t je teď 64bitová hodnota (pokud není definována _USE_32BIT_TIME_T).

  • Funkce _spawn, _wspawn nyní ponechají errno nedotčený při úspěchu, jak je specifikováno standardem C.

  • RtC teď ve výchozím nastavení používá široké znaky.

  • Funkce podpory řídicího slova pro operace s plovoucí desetinnou čárkou jsou doporučeny nepoužívat pro aplikace zkompilované pomocí /CLR nebo /CLR:PURE. Ovlivněné 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 teď vrací ukazatele const. Staré, ne-konstantní chování lze obnovit definováním _CONST_RETURN. Ovlivněné funkce jsou

    • memchr, wmemchr

    • strchr, wcschr, _mbschr, _mbschr_l

    • strpbrk, wcspbrk, _mbspbrk, _mbspbrk_l

    • strrchr, wcsrchr, _mbsrchr, _mbsrchr_l

    • strstr, wcsstr, _mbsstr, _mbsstr_l

  • Při propojení s Setargv.obj nebo Wsetargv.obj už není možné potlačit rozšíření zástupného znaku na příkazovém řádku uzavřením do dvojitých uvozovek. Další informace naleznete v tématu Expanze zástupných znaků v argumentech.

Standardní knihovna (2005)

  • Třída výjimky (umístěná v <exception> hlavičce) byla přesunuta do std oboru názvů. V předchozích verzích byla tato třída v globálním oboru názvů. Pokud chcete vyřešit případné chyby, které značí, že třídu výjimek nelze najít, přidejte do kódu následující příkaz using: using namespace std;

  • Při volání valarray::resize()dojde ke ztrátě obsahu valarray a nahradí se výchozími hodnotami. Metoda resize() je určena k opětovnému inicializování valarray spíše než k jeho dynamickému růstu jako u vektorů.

  • Ladicí iterátory: Aplikace vytvořené pomocí ladicí verze knihovny C-Runtime, které používají iterátory nesprávně, mohou začít zobrazovat aserty za běhu. Chcete-li tyto aserce zakázat, je potřeba definovat _HAS_ITERATOR_DEBUGGING (nahrazeno _ITERATOR_DEBUG_LEVEL počínaje Visual Studiem 2010) na 0. Více informací naleznete v tématu Podpora ladicího iterátoru.

Zásadní změny visual C++ .NET 2003

kompilátor

  • Uzavírací závorky se teď vyžadují pro definovanou direktivu preprocesoru (C2004).

  • Explicitní specializace už nenaleznou parametry šablony z primární šablony (Chyba kompilátoru C2146).

  • Chráněný člen (n) je přístupný pouze prostřednictvím členské funkce třídy (B), která dědí z třídy (A), z níž (n) je členem (Chyba kompilátoru C2247).

  • Vylepšené kontroly přístupnosti v kompilátoru teď detekují nepřístupné základní třídy (chyba kompilátoru C2248).

  • Výjimku nelze zachytit, pokud je destruktor a/nebo konstruktor kopírování nepřístupný (C2316).

  • Výchozí argumenty u ukazatelů na funkce už nejsou povolené (Chyba kompilátoru C2383).

  • Statický datový člen nelze inicializovat prostřednictvím odvozené třídy (Chyba kompilátoru C2477).

  • Inicializace typedef standardu není povolená a teď generuje chybu kompilátoru (Chyba kompilátoru C2513).

  • bool je teď správný typ (chyba kompilátoru C2632).

  • UDC teď může vytvořit nejednoznačnost s přetíženými operátory (C2666).

  • Další výrazy jsou nyní považovány za platné konstanty ukazatele null (Chyba kompilátoru C2668).

  • Šablona<> je teď vyžadována na místech, kde by kompilátor dříve předpokládal (chyba kompilátoru C2768).

  • Explicitní specializace členské funkce mimo třídu není platná, pokud už je funkce explicitně specializovaná prostřednictvím specializace podle třídy šablony (Chyba kompilátoru C2910).

  • Parametry šablony netypového parametru čísla s plovoucí desetinnou čárkou již nejsou povoleny (Chyba kompilátoru C2993).

  • Šablony tříd nejsou povolené jako argumenty typu šablony (C3206).

  • Názvy přátelských funkcí již nejsou vkládány do obsahujícího oboru názvů (Chyba kompilátoru C3767).

  • Kompilátor už nebude přijímat nadbytečné čárky v makru (C4002).

  • Objekt typu POD vytvořený inicializátorem formuláře () bude ve výchozím nastavení inicializován (C4345).

  • Název typename se teď vyžaduje, pokud se závislý název považuje za typ (upozornění kompilátoru (úroveň 1) C4346).

  • Funkce, které byly nesprávně považovány za specializace šablon, se už nepovažují za (C4347).

  • Statické datové členy nelze inicializovat prostřednictvím odvozené třídy (C4356).

  • Specializaci šablony třídy je potřeba definovat před jejím použitím v návratovém typu (upozornění kompilátoru (úroveň 3) C4686).

  • Kompilátor teď hlásí nedostupný kód (C4702).

Viz také

Co je nového pro Visual C++ v sadě Visual Studio