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

Tento článek popisuje všechny zásadní změny sady Visual Studio 2015, které se vrátí do sady Visual Studio 2003, a v tomto článku se termíny "nové chování" nebo "teď" týkají sady Visual Studio 2015 a novější. 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.

Nikdy byste neměli psát kód, který závisí na konkrétním rozložení objektu, který není rozhraním MODELU 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 hranicí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 refaktorová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 Linker projektu Ignorovat všechny výchozí knihovny na Ano nebo používáte /NODEFAULTLIB možnost linkeru na příkazovém řádku, musíte aktualizovat seznam knihoven (ve vlastnosti Další závislosti), aby zahrnovaly 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é verze (.lib) a dynamické verze (.dll) a 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 modulu runtime VC, , libvcruntime.libvcruntimeversion.dll, libvcruntimed.liba vcruntimedversion.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 vrátila lconv data pro globální národní prostředí, nikoli národní prostředí 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čce. Kód, který obsahuje <math.h> pouze 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, uveďte <cmath> 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)
    • floata long double verze funkcí s plovoucí desetinou čárkou acos, , atanh, tgammatantanhsqrtacoshasinasinhatanatan2cbrtceilcopysigncoscosherferfcexpexp2expm1fabsfdimfloorfmafmaxfminfmodfrexphypotilogbldexplgammallrintllroundloglog10log1plog2lrintlroundmodfnearbyintnextafternexttowardremainderremquorintroundscalblnscalbnsinsinhtrunc

    Pokud máte kód, který se používá abs s typem s plovoucí desetinou čárkou, který obsahuje <math.h> pouze záhlaví, verze s plovoucí desetinou čárkou už nebudou k dispozici. Volání se teď vyřeší abs(int)i s argumentem s plovoucí desetinou čárkou, která způsobí 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í desetinou čárkou abs, například fabs pro dvojitý argument nebo fabsf plovoucí argument, nebo zahrnout <cmath> záhlaví a pokračovat v použití abs.

  • Shoda s plovoucí desetinou čárkou

    Mnoho změn matematické knihovny bylo provedeno za účelem zlepšení souladu se specifikacemi IEEE-754 a C11 přílohy F s ohledem na zvláštní vstupy malých a malých písmen, jako jsou nan a infinity. Například tiché vstupy NaN, které byly často považovány za chyby v předchozích verzích knihovny, se už nezachází jako s chybami. 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 z knihovny DLL knihovny modulu runtime exportovány nové a delete funkce definované implementací (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

    _beginthreadex Funkce _beginthread teď obsahují odkaz na modul, ve kterém je procedura vlákna definována po dobu trvání vlákna. To pomáhá zajistit, aby se moduly nenačítá, dokud se vlákno nespustí do dokončení.

<stdarg.h>

  • va_start a odkazové typy

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

<stdio.h> a <conio.h>

  • Řada funkcí printf a scanf je teď definovaná jako vložená.

    Definice všech printf funkcí byly scanf přesunuty vložené do <stdio.h>, <conio.h>a další hlavičky CRT. Tato změna způsobující chybu vede k chybě linkeru (LNK2019, nevyřešený externí symbol) pro všechny programy, které tyto funkce deklarovaly místně bez zahrnutí příslušný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, potom v dialogovém okně Vlastnosti projektu, zvolte Linker a upravte vstup linkeru, který chcete přidat 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.

    Upozorňující

    Pokud propojíte se sadou Windows SDK 8.1 nebo staršími verzemi, může dojít k těmto nevyřešeným chybám 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ů se můžete pokusit 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 získání 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í Microsoftu, které bylo ekvivalentní k získání, 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 definice a sítě NAN naformátovaly pomocí sady řetězců sentinelu specifických pro MSVC.

    • Nekonečno: 1,#INF

    • Quiet NaN: 1.#QNAN

    • Signaling NaN: 1.#SNAN

    • Neurčené 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 definice a sítě NaN. Implementace MSVC teď vyhovuje těmto požadavkům. Nové řetězce jsou následující:

    • Nekonečno: inf

    • Quiet NaN: nan

    • Signaling NaN: nan(snan)

    • Neurčené naN: nan(ind)

    Každá z těchto možností může být předponou 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ází printfscanfa .

  • Formátování a analýza s plovoucí desetinou čárkou

    Byly zavedeny nové algoritmy formátování a analýzy s plovoucí desetinou čá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 by mohly generovat řetězce, které by se vrátily zpět na původní hodnotu s plovoucí desetinnou čárkou, ale nebyly skvělé, pokud byste chtěli přesnou hodnotu (nebo 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). Příkladem zlepšení; při tisku velkého výkonu dvou možností vezměte v úvahu výsledky:

    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í způsobující chybu, protože tyto funkce můžou výstupem různých výsledků. Nové výsledky jsou vždy správnější než staré výsledky.

  • Hexadecimální a nekonečno/Parsování plovoucí desetinné čárky NaN

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

  • %A a %a nula odsazení

    Specifikátory formátu %a %A formátují číslo s plovoucí desetinnou čárkou jako šestnáctkové mantisy a binární exponent. V předchozích verzích printf by funkce nesprávně použily řetězce s nulovou nulou. Například printf("%07.0a\n", 1.0) by se tiskl 00x1p+0, kde by se měl vytisknout 0x01p+0. Tato chyba byla opravena.

  • %A a %a přesnost

    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á specifikátoru formátu %f s tím rozdílem, že infinity a sítě NAN jsou formátovány 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 věku segmentovaných adresních prostorů: tyto modifikátory délky byly použity k označení vzdálený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 čárku 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 sadě Visual Studio 2005 byl přidán 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 exponentu při tisku odpovídající standardům.

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

    V předchozích verzích printf by funkce scanf bezobslužně 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

    Vpředchozíchch fopenr+b+ Řetězce režimu jsou nyní zjištěny a považovány za neplatné parametry.

  • režim _O_U8TEXT

    Funkce _setmode nyní správně hlásí režim datových proudů otevřených in_O_U8TEXT režimu. V předchozíchverzích _O_WTEXT ch

    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 před zahrnutím <stdio.h>souboru snprintf nebo vsnprintf definován jako makro , 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 uživatelského kódu nebo vsnprintf v kódu uživatele.

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

    V předchozích verzích tmpnam a tmpnam_s funkce 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íchverzích <stdio.h> 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 funkce se nepodařilo nastavit errno na ERANGE, pokud hodnota nebyla reprezentovatelná jako float. Tato chyba byla specifická pro tyto dvě funkce; , strtodwcstodstrtolda wcstold funkce nebyly ovlivněny. Tento problém je opravený a jedná se o změnu způsobující chybu za běhu.

  • 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 byly nefunkční od aktualizace CRT tak, aby používaly haldu Windows.

  • smallheap

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

  • _Stat

    Řada _stat funkcí se používá CreateFile v sadě Visual Studio 2015 místo FindFirstFile jako v sadě Visual Studio 2013 a starší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. V předchozích verzích knihovny byl podpis 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 deklarováno jako zastaralé. V kódu jazyka C můžete define_CRT_NON_CONFORMING_WCSTOK způsobit _wcstok použití místo wcstok.

<time.h>

  • clock

    V předchozích verzích clock byla funkce implementována pomocí rozhraní API GetSystemTimeAsFileTimesysté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 _statfstat, a _utime funkce zpracovávají letní čas nesprávně. Před sadou Visual Studio 2013 všechny tyto funkce nesprávně upravily standardní časy, jako by byly v letním čase.

    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. _utime Nyní fstat byly opraveny řadu funkcí, takže všechny tyto funkce nyní zpracovávají letní čas správně a konzistentně.

  • asctime

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

  • strftime a wcsftime

    wcsftime Funkce strftime 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++

Pokud byte chtěli povolit nové optimalizace a kontroly ladění, implementace standardní knihovny C++ záměrně neumožňuje binární kompatibilitu mezi verzemi. Proto při použití standardní knihovny C++ nelze objektové soubory a statické knihovny, které jsou kompilovány pomocí různých verzí, směšovat v jednom binárním souboru (EXE nebo DLL) a objekty standardní knihovny C++ nelze předávat mezi binárními soubory, které jsou kompilovány pomocí různých verzí. Takovéto směšování objektů vyvolává chyby linkeru týkající se neshod _MSC_VER. (_MSC_VER je makro, které obsahuje hlavní verzi kompilátoru – například 1800 pro Visual Studio 2013.) Tato kontrola nedokáže 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čce standardní knihovny C++ byly provedeny některé změny struktury zahrnutí. Hlavičky standardní knihovny jazyka C++ mohou navzájem obsahovat nespecifikované způsoby. 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é, nyní deklaruje std::array bez zahrnutí všech <array>, které mohou přerušit kód pomocí následující kombinace konstruktorů kódu: váš kód má proměnnou s názvem "array" a máte direktivu using-direktivu "using namespace std;" a zahrnete hlavičku standardní knihovny jazyka C++ (například <functional>) zahrnující <tuple>, která nyní deklaruje std::array. <tuple>

  • 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 v sadě Visual Studio steady_clock::time_point nyní typedef pro chrono::time_point<steady_clock>; to však nemusí nutně být případ pro jiné implementace.

  • alokátory a const

    Nyní vyžadujeme porovnávání rovnosti a nerovnosti alokátoru, abychom přijali argumenty const 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::d eallocate

    V sadě Visual Studio 2013 a starší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í soubory <hash_map> hlaviček a <hash_set> jsou zastaralé v sadě Visual Studio 2015 a v budoucí verzi se odeberou. Použijte <unordered_map> a <unordered_set> místo toho.

  • komparátory a operátory()

    Asociativní kontejnery ( <map> rodina) teď vyžadují, aby jejich komparátory měly operátory volání funkce s možností kont-callable. 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. V jazyce C++11 byly změněny a byly 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
    add_reference add_lvalue_reference
    has_default_constructor is_default_constructible
    has_copy_constructor is_copy_constructible
    has_move_constructor is_move_constructible
    has_nothrow_constructor is_nothrow_default_constructible
    has_nothrow_default_constructor is_nothrow_default_constructible
    has_nothrow_copy is_nothrow_copy_constructible
    has_nothrow_copy_constructor is_nothrow_copy_constructible
    has_nothrow_move_constructor is_nothrow_move_constructible
    has_nothrow_assign is_nothrow_copy_assignable
    has_nothrow_copy_assign is_nothrow_copy_assignable
    has_nothrow_move_assign is_nothrow_move_assignable
    has_trivial_constructor is_trivially_default_constructible
    has_trivial_default_constructor is_trivially_default_constructible
    has_trivial_copy is_trivially_copy_constructible
    has_trivial_move_constructor is_trivially_move_constructible
    has_trivial_assign is_trivially_copy_assignable
    has_trivial_move_assign is_trivially_move_assignable
    has_trivial_destructor is_trivially_destructible
  • launch::any a launch::sync policies

    Nestandardní launch::any zásady a launch::sync zásady byly odebrány. Místo toho pro launch::anypoužití launch:async | launch:deferred. Pro launch::syncpoužití launch::deferred. Viz spuštění výčtu.

Rozhraní MFC a knihovna 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í panely řídit 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í. Tato #undef akce byla odebrána a byla přidána nová nekonfliktní ekvivalentní volání rozhraní API concurrency::Context::YieldExecution . Pokud chcete obejít konflikty s funkcí Yield, můžete aktualizovat kód tak, aby místo toho volal YieldExecution funkci, nebo název funkce ohraničovat Yield do závorek na webech 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 jiné chyby nebo dokonce na rozdíly v chování v kódu, který jste dříve vytvořili a zdáli se, že jsou 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é můžou být potřeba změnit (před) a opravy pro jejich opravu (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í shody v sadě Visual Studio 2015

  • /Zc:forScope- možnost

    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ž nelze spouštět z příkazového řádku s mstest.exe. Místo toho použijte vstest.console.exe. Viz možnosti příkazového řádku VSTest.Console.exe.

  • 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

    V systému typedef už nemůžete používat char16_t aliasy, char32_t 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) funkce. 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 copy konstruktor pro váš objekt 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 pro odkaz 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éhokoli zásahu prázdných znaků interpretují jako literály definované uživatelem, což může vést k chybám nebo 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 rozbalené do "tam", a potom byly dva řetězcové literály zřetězeny 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 souvisejícím změnám analýzy řetězců v sousedních řetězcových literálech (širokých nebo úzkých znakových literálech) bez prázdných znaků interpretovaly jako jediný zřetězený řetězec v předchozích verzích Visaul C++. V sadě Visual Studio 2015 teď musíte mezi dva řetězce přidat prázdné znaky. 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í

    Operátor provedl delete změnu, aby ji mohl převést do souladu se standardem C++14. Podrobnosti o změně standardů najdete v sadě 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 novému operátoru umístění), zobrazí se chyba kompilátoru (C2956, ke kterému dochází v okamžiku, kdy se použije nové umístění, protože se jedná 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. U zrušení přidělení velikosti C++14 je tato funkce delete nyní obvyklou funkcí deallocation (globální delete 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 nové umístění i odstranění umístění:

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

    K problému dochází z důvodu shody v podpisech funkce mezi operátorem odstranění umístění, který jste definovali, a novým operátorem globální velikosti delete . Zvažte, jestli můžete použít jiný typ než size_t pro jakékoli nové umístění a delete operátory. Typ je závislý na kompilátoru size_ttypedef ; je typedef to pro unsigned int v MSVC. Dobrým řešením je použít výčtový typ, například tento:

    enum class my_type : size_t {};
    

    Pak změňte definici umístění nové a delete použít tento typ jako druhý argument místo size_t. Budete také muset aktualizovat volání nového umístění tak, aby předala nový typ (například pomocí static_cast<my_type> převodu z celočíselné hodnoty) a aktualizovat definici new a delete přetypovat zpět na typ celého čísla. 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 nové umístění . Pokud váš kód používá nové umístění pro implementaci fondu paměti, ve kterém je argument umístění velikost objektu přidělený nebo odstraněný, může být funkce přidělení velikosti vhodná k nahrazení vlastního kódu fondu paměti a můžete se zbavit funkcí umístění a použít pouze vlastní operátor dvou argumentů 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 odstranění se dvěma argumenty neexistují a nezpůsobí konflikt s operátorem odstranění umístění.

  • Sjednocovat datové členy

    Datové členy sjednocení už nemůžou 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 může také změnit velikost sjednocení.

  • Anonymní sjednocení jsou nyní v souladu se standardem. Předchozí verze kompilátoru vygenerovaly explicitní konstruktor a destruktor pro anonymní sjednocení. 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 ve sjednocení již není implicitně volána při vytvoření takové sjednocení. Destruktor pro anonymní členy struktury ve sjednocení se také implicitně nevolá, když sjednocení 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;
    }
    

    V sadě Visual Studio 2013 se při vytvoření sjednocení volá konstruktor pro S a při vyčištění zásobníku pro funkci f se volá destruktor pro S. V sadě Visual Studio 2015 se ale konstruktor a destruktor nevolá. 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 konstruktor a destruktor kódu do nových funkcí a přidat volání těchto funkcí z konstruktoru a destruktoru pro sjednocení.

    #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

    Změny překladu názvů pro šablony byly provedeny. V jazyce C++ může při zvažování kandidátů na překlad jména dojít k tomu, že jedna nebo více jmen, které je třeba vzít v úvahu 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í

    V sadě Visual Studio 2013 i Visual Studio 2015 kompilátor vygeneruje konstruktor kopírování pro třídu, pokud má tato třída konstruktor přesunutí definovaný uživatelem, ale žádný konstruktor kopírování 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í vytvoří C266: "N::bind": nejednoznačné volání přetížené funkce.

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

    Chcete-li chybu opravit, můžete plně kvalifikovat bind: N::bind(...)volání na . 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 nyní vytvoří C2440: '=': nemůže převést z '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"; Literal operator or literal operator template 'operator ""L' not found

    #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). Teď se parsuje 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ů.

  • Odebraný prázdný znak 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írovat 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 ji = 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í v inicializaci nestatického datového členu (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 proS2:S

    class S {
        S();
        friend class S2; // Make S2 a friend
    public:
        int i;
    };
    
  • Výchozí ctor 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;
    }
    

    Pokud chcete chybu opravit, odeberte potřebu volat výchozí konstruktor. 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, odeberte závorky z okolí 0 nebo jiného použití nullptr , jak je znázorněno v tomto příkladu:

    struct S {
        S() : p(nullptr) {}
        void *p;
    };
    
  • Nesprávná definice a použití maker v závorkách

    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 jeden výraz.

    Následující kód nyní vytvoří chybu C3518: testPositions: v kontextu direct-list-initialization, který typ pro "auto" lze 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 teď způsobí selhání statického kontrolního výrazu.

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

    Pokud chcete chybu opravit, změňte ji static_assert tak, aby porovnávala ukazatele na D :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 (za)

    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 and operator delete

    Předchozí verze kompilátoru umožňovaly, aby byl nový a nečlenový operátor odstraněný jako statický a deklarován v jiných oborech názvů než globální obor názvů. Toto staré chování vytvořilo riziko, že program nebude volat new implementaci nebo delete operátora, kterou program chtěl, což vede k tichému špatnému chování za běhu. 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 (za)

    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, zatímco bezobslužné ignorování. 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 (za)

    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 byly povoleny typename ve specifikátoru propracované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 (za)

    template <class T>  // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case
    class container;
    
  • Odpočty typů polí 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í, které program zamýšlen.

    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 (za)

    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 řešení přetížení považuje za dalšího kandidáta, který je lepší než historický kandidát, volání jednoznačně vyřeší nový kandidát, což způsobí změnu chování programu, která se pravděpodobně liší od programátora.

    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 rozlišení přetížení (po)

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

    Předchozí verze kompilátoru odebrala některá upozornění související s switch příkazy. Tato upozornění se teď obnovila. Kompilátor nyní vydává obnovená upozornění a upozorně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 případ off-end, nikoli na posledním řádku příkazu switch. 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 podle očekávání, může být nutné přesunout #pragma warning(disable:####) direktivu na řádek nad prvním případem urychlování. 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 (za)

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

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

  • #include: použití specifikátoru nadřazeného adresáře .. in pathname (pouze ovlivňuje /Wall/WX)

    Předchozí verze kompilátoru nezjistily použití specifikátoru nadřazeného adresáře .. v pathname 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 (za)

    #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() rozšiřuje poslední konec souboru hlaviček (pouze ovlivňuje /Wall/WX)

    Předchozí verze kompilátoru nezjistily změny nastavení příznaku optimalizace, které uchytí hlavičkový soubor zahrnutý v jednotce překladu. Kompilátor nyní zjistí a upozorní programátora na kód napsaný tímto způsobem a vydá volitelné upozornění kompilátoru C4426 v umístění přesměrování #include, pokud je povoleno. 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 (za)

    // 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) (pouze ovlivňuje/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 by program byl zkompilován s jinou sadou upozornění povolených než programátor zamýšlený, což může mít za následek tiché špatné chování modulu runtime. Kompilátor nyní rozpozná a upozorní programátora kódu napsaného tímto způsobem a vydá volitelné upozornění kompilátoru C5031 v umístění odpovídajícího #pragma warning(pop)kódu , 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 (za)

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

    I když je kód napsaný tímto způsobem často ú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 spravily stav upozornění vlastním způsobem.

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

    Předchozí verze kompilátoru nezjistily chybějící #pragma warning(push) změny stavu na konci jednotky překladu. Kompilátor nyní rozpozná a upozorní programátora kódu napsaného tímto způsobem a vydá volitelné upozornění kompilátoru C5032 v umístění chybějícího #pragma warning(push)souboru , 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 (za)

    // 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 #pragma stavu upozornění, které nejsou dostatečně dobré k vydání všech zamýšlených upozornění. Toto chování vytvořilo riziko, že určitá upozornění by byla účinně potlačena za okolností odlišných od programátora. 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á dříve nesprávně potlačená nebo upozornění související s dříve chybně diagnostikovanými problémy.

  • 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ějším vydaný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 (za)

    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 (za)

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

    Když toto nové chování analyzuje decltype výraz, který chybí nezbytné použití klíčového typename slova k urč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 (za)

    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á volatile členské proměnné, aby měly operátory konstrukce a přiřazení nesouvisejí s triviálními operátory, 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 (za)

    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í kvalifikátory cv.

    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(za)

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

    Kód zkompilovaný pro prostředí Windows Runtime (WinRT) neumožňuje enum deklaraci typů, podobně jako při kompilaci spravovaného kódu C++ pro rozhraní .Net Framework pomocí 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 (za)

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

    Předchozí verze kompilátoru nevyvolají upozornění, pokud jsou vložené funkce pro odstranění operátoru, který není členem. Kód napsaný tímto způsobem je špatně vytvořený (nevyžaduje se diagnostika) a může způsobit problémy s pamětí způsobené neshodou nových operátorů a operátorů odstranění (zejména při použití společně s přidělením velikosti), které může být obtížné diagnostikovat. Kompilátor teď vydá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 (za)

    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 std::is_convertable vlastnosti typu nezjistily správně přiřazení typu třídy při odstranění nebo privátním konstruktoru kopírování. std::is_convertable<>::value Nyní je správně nastaven na false při použití na typ třídy s odstraněný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é kontrolní výrazy v dolní části tohoto příkladu pass, protože std::is_convertable<>::value byl nesprávně nastaven na true. std::is_convertable<>::value Nyní je správně nastaven na false, což způsobuje selhání statických kontrolních výrazů.

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

    Předchozí verze kompilátoru nezkontrolovaly specifikátor přístupu 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 výchozího nebo odstraněného triviálního kopírování a konstruktory přesunutí, aby zjistil, jestli se dá volat, a pokud ne, vydá upozornění kompilátoru C2248 v důsledku toho.

    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 (za)

    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 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 (za)

    __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 (za)

    #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ňují /Wall/WX)

    Předchozí verze kompilátoru přijímaly neshodné #include direktivy ve zdrojových souborech mezi -Yc a -Yu kompilacemi 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 (za)

    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 neshodované 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 teď vydává upozornění kompilátoru CC4599, aby při použití souborů PCH pomohl identifikovat neshodované argumenty adresáře () v adresáři .-I

    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 (za)

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

Změny shody sady Visual Studio 2013

Compiler

  • 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 se nevystavila chyba, protože volání bylo virtual volání. Program by ale za běhu chybově ukončil. Nyní je přiřazena chyba linkeru, protože třída je nyní označena jako konečná. V tomto příkladu, chcete-li opravit chybu, byste propojit s obj, který obsahuje definici S2::f.

  • Při použití přátelských funkcí v oborech názvů je nutné před odkazem na tuto funkci znovu před odkazem na tuto funkci nebo 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ídá standardu ISO C++11, následující kód by se zkompiloval a způsobil x překlad typu int:

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

    Tento kód se nyní přeloží x na typ std::initializer_list<int> a způsobí chybu na dalším řádku, který 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, bylo místo chyby vydáno upozornění kompilátoru (ú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;
    }
    

    V sadě Visual Studio 2012 E1 se výraz E1::b přeložil na ::E1 globální obor. V sadě Visual Studio 2013 E1 se ve výrazu E1::b překládá na typedef E2 definici 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 by se optimalizace pro platformu x64 pokusila vylepšit rozložení za vás, ale protože v složitých situacích s kódem nefungovala správně, byla odebrána v sadě Visual Studio 2013. Podívejte se například na tento kód:

    __declspec(align(16)) struct S1 {
    };
    
    struct S2 {
        virtual ~S2();
        void *p;
        S1 s;
    };
    
  • V sadě Visual Studio 2013 je výsledek x64 sizeof(S2) 48, ale v předchozích verzích se vyhodnotí 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>. I když ratio_add<R1, R2>::type už to není nutné a nyní doporučujeme, abyste řekli ratio_add<R1, R2>, že se první zkompiluje, protože ratio<N, D> je nutné mít "typ" pro snížený poměr, což bude stejný typ, pokud je již 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 v předchozí verzi – tradiční neskopované výčty zabalené v oborech názvů – 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í převody na logickou hodnotu ( například vzhledem k tomu shared_ptr<X> sp, že jsou static_cast<bool>(sp) platné a bool b(sp) jsou platné) a logické testovatelné "kontextové převody" na logickou hodnotu – například if (sp), !sp, sp && cokoliv. explicit operator bool() Zakáže však implicitní převody na logickou hodnotu, takže nemůžete říci bool b = sp; a dát logický návratový typ, 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. Je-li potvrzen náš nástroj maker určený k podpoře simulovaných variadic šablon jiným způsobem, je nutné změnit váš kód.

  • Kromě běžných klíčových slov teď hlavičky standardní knihovny jazyka C++ zakázaly nahrazení makra přepsání a konečných klíčových slov citlivých na kontext.

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

  • <random> nyní přísně vynucuje své předpoklady pro kompilaci.

  • 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 měla common_type<> neočekávané a nežádoucí důsledky, zejména vrací common_type<int, int>::type .int&& Kompilátor proto implementuje navrhované řešení problému pracovní skupiny knihovny 2141, který vrací common_type<int, int="">::typeint.

    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 požadujete vlastnost typu identity, nepoužívejte nestandardní std::identity vlastnost, která je definována, <type_traits> protože 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;
    };
    

Rozhraní MFC a knihovna ATL

  • Pouze Visual Studio 2013: Knihovna MFC MBCS není součástí sady Visual Studio, protože Unicode je tak populární a použití služby MBCS se výrazně odmítlo. Tato změna také udržuje MFC lépe zarovnané s Windows SDK, protože mnoho ovládacích prvků a zpráv má pouze kódování Unicode. Pokud však 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 se změní. 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ádají zašifrované a dešifrují se jenom podle potřeby. Nedá se vrátit jako prostý text. Řetězec lze získat pomocí CDatabase::Dump metody.

  • CWnd::OnPowerBroadcast Podpis se změní. Podpis tohoto popisovače zprávy se změní na LPARAM jako druhý parametr.

  • Podpisy se změní tak, aby vyhovovaly obslužné rutině 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 namísto (WPARAM, LPARAM) na (UINT, int, int) tak, aby bylo možné nové ON_WM_DISPLAYCHANGE makro použít v mapě zpráv.

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

    • CFrameWnd::OnDDEExecute namísto (WPARAM, LPARAM) se změnila na (CWnd*, HANDLE), aby bylo možné v mapě zpráv použít nové ON_WM_DDE_EXECUTE makro.

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

    • 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ěna na žádné parametry místo (WPARAM, LPARAM), aby bylo možné nové ON_WM_PASTE makro použít 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 (WINVER < 0x0501) jsou odebrány různé #ifdef direktivy.

  • Knihovna DLL ATL (atl120.dll) je odebrána. 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 se odebere společně s knihovnou DLL KNIHOVNY ATL a mechanismus trasování je zjednodušený. Konstruktor CTraceCategory teď přebírá jeden parametr (název kategorie) a makra TRACE volají funkce generování sestav ladění CRT.

Zásadní změny sady Visual Studio 2012

Compiler

  • 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, enum klíčové slovo třídy definuje výčt C++11, 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 šablony můžete explicitně zrušit nejednoznačný název 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 Překlad 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 /GS řádku a který má ohrožení zabezpečení mimo jeden, může vést k ukončení procesu za běhu, 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 se změní na SSE2; kompilátor proto může generovat instrukce SSE a použije registru 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, pokud předtím ne. Kompilátor používá silnější kontroly použití neinicializovaných místních proměnných typu ukazatele.

  • Pokud je zadán 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 se takové přidělení častěji vracely adresy, které byly menší než 2 GB.) Tato změna může vystavit chyby zkrácení ukazatele 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 /HIGHENTROPYVA spravované sestavení. V tomto případě /HIGHENTROPYVAswitch je ale ve výchozím nastavení vypnutý.

IDE

  • Přestože doporučujeme nevytvořit model Windows Forms aplikace v C++/CLI, podporuje se údržba stávajících aplikací uživatelského rozhraní C++/CLI. Pokud potřebujete vytvořit model Windows Forms aplikaci nebo jinou aplikaci uživatelského rozhraní .NET, použijte jazyk 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ý. UmsThreadDefault Specifikace vytvoří zastaralé upozornění a interně se mapuje zpět na ThreadScheduler.

Standardní knihovna

  • Po změně způsobující chybu mezi standardy C++98/03 a C++11 pomocí explicitních argumentů šablony, které se mají volat make_pair() – stejně jako v make_pair<int, int>(x, y) – se obvykle nekompiluje v sadě Visual C++ v sadě 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íchargumentch 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 se A implicitně konvertibilní na B a B implicitně převede na jazyk C, ale A není implicitně převést na C, C++98/03 a Visual Studio 2010 je povoleno pair<A, X> převádět (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>&)volání func() s pair<const char *, const char *> touto změnou se zkompiluje. 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>.

  • Simulované variadické šablony sady Visual Studio 2010 , například make_shared<T>(arg1, arg2, argN)– až do limitu 10 argumentů, pomocí razítka přetížení a specializace pomocí preprocesorových strojů. 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 zakáže nahrazení klíčových slov 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 v sadě Visual C++ v sadě 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() měl by přijímat upravitelné stateT& parametry, ale Visual Studio 2010 trvalo 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 nové a malloc(), už není soukromá. CRT teď používá haldu procesu. To znamená, že halda není zničena při uvolnění knihovny DLL, takže knihovny DLL, které se staticky propojí s CRT, musí zajistit, aby paměť přidělená kódem knihovny DLL byla vyčištěna před jeho 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()je například , 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.

Rozhraní MFC a knihovna ATL

  • Odebrání podpory fusion (afxcomctl32.h); proto 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ěna podpisu CFileDialog::SetDefExt pro použití LPCTSTR, proto jsou ovlivněny buildy Unicode.

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

  • Změna podpisu CBasePane::MoveWindow tak, aby přebísněl znak .const CRect

  • Změnil se podpis .CMFCEditBrowseCtrl::EnableBrowseButton

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

  • Přidání parametru CMFCRibbonStatusBarPane do konstruktorů (Jedná se o výchozí parametr, a proto se nejedná o zásadní zdroj.)

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

  • Odebrali AFXTrackMouse jsme rozhraní API (a související časovač). Místo toho použijte rozhraní API Win32 TrackMouseEvent .

  • Přidání parametru do konstruktoru CFolderPickerDialog (Jedná se o výchozí parametr, a proto se nejedná o zásadní 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 vždy TRUE ve Windows Vista, Windows 7 a Windows 8.

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

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

  • Odebrané 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 tak, aby IsDwmCompositionEnabled 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ěna podpisu OnExitSizeMove metody tak, aby souhlasila s makrem ON_WM_EXITSIZEMOVE:

    • CFrameWndEx

    • CMDIFrameWndEx

    • CPaneFrameWnd

  • Změna názvu a podpisu souhlasu OnDWMCompositionChanged 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 ReplaceThisText

    • CMFCToolBarComboBoxEdit

    • CMFCToolBarEditCtrl

    • CMFCAutoHideBar

  • Změna podpisu souhlasu OnPowerBroadcast s makrem ON_WM_POWERBROADCAST:

    • CFrameWndEx

    • CMDIFrameWndEx

  • Změna podpisu souhlasu OnStyleChanged s makrem ON_WM_STYLECHANGED:

    • CMFCListCtrl

    • CMFCStatusBar

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

  • Odebrali jsme mnoho globálních statických CString objektů, aby se v některých situacích vyloučilo nevracení paměti (nahrazeno #defines) a 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ěnili jsme podpis parametru oddělovače akcelerátoru a odebrali ho CKeyboardManager::ShowAllAccelerators .

  • Přidána CPropertyPage::GetParentSheet, a ve CPropertyPage třídě, zavolejte ji namísto GetParent získání správného nadřazeného okna listu, který může být nadřazený nebo grandparent 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ůsobilo nesprávné zakázání upozornění. Tato upozornění jsou teď po ATLBASE správně povolená. H byl analyzován.

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

    • GetDirectD2dFactory

    • GetWriteFactory

    • GetWICFactory

    • InitD2D

    • ReleaseD2DRefs

    • IsD2DInitialized

    • D2D1MakeRotateMatrix

    • Místo volání, například afxGlobalData.IsD2DInitialized, volání AfxGetD2DState->IsD2DInitialized.

  • Odebrání zastaralé knihovny ATL*. Soubory CPP ze složky \atlmfc\include\.

  • Inicializace byla přesunuta afxGlobalData na vyžádání místo v době inicializace CRT, aby splňovala DLLMain požadavky.

  • RemoveButtonByIndex Přidání metody do CMFCOutlookBarPane třídy.

  • Opraveno CMFCCmdUsageCount::IsFreqeuntlyUsedCmd na IsFrequentlyUsedCmd.

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

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

  • Odebrané CDockablePane statické členské proměnné m_bCaptionText a m_bHideDisabledButtons.

  • Přidání metody přepsání 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

Compiler

  • 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 podporu 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é opouštějí proces v neopravitelném poškozeném stavu. 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 do zásobníku vložit další kontroly zabezpečení, 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 pomocí možností /GL kompilátoru /GL (Kdo le Program Optimization) i /clr (Common Language Runtime Compile), bude tato možnost ignorována. Tato změna byla provedena, protože kombinace možností kompilátoru poskytovala malou výhodu. V důsledku této změny se zlepší 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ýchsouborch

  • 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 sadě Visual Studio 2010, RuntimeLibrary = MultiThreaded (/MD) a DebugInformationFormat = ProgramDatabase (/Zi). Ve Visual C++ 9.0, RuntimeLibrary = MultiThreaded (/MT) a DebugInformationFormat = Disabled.

CLR

  • Kompilátory jazyka Microsoft C# a Visual Basic teď můžou vytvořit žádné primární sestavení vzájemné spolupráce (no-PIA). Sestavení bez PIA může používat typy MODELU COM bez nasazení relevantního primárního sestavení vzájemné spolupráce (PIA). Při využívání sestavení bez PIA vytvořených v jazyce Visual C# nebo Visual Basic je nutné odkazovat na sestavení PIA na příkaz kompilace před odkazem na jakékoli sestavení no-PIA, které používá 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í by mohl importovat podřízený seznam vlastností a nadřazený objekt může k definování dalších proměnných použít proměnnou definovanou v podřízené části. Pozdní vyhodnocení umožnilo nadřazené použití podřízené proměnné i před importem podřízeného seznamu vlastností. 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í.

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 modul runtime, aby ho 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 Sejf Int je součástí visual C++ a již není v samostatném stažení. Jedná se o zásadní změnu pouze v případě, že jste vyvinuli třídu s názvem "Sejf Int".

  • 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 můžete znovu sestavit knihovny běhu. 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.

  • <algorithm> V záhlaví checked_* se odeberou funkceunchecked_*. A v <iterator>> záhlaví checked_iterator se třída odebere 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.

  • Ordinaly se už nepoužívají v souborech definice modulu MFC (.def). Tato změna znamená, že se ordinaly nebudou lišit mezi podverzemi a binární kompatibilitou pro aktualizace Service Pack a bude vylepšena technická verze pro rychlé opravy.

  • 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. Tato proměnná prostředí se odebere a nenahradí se.

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, .8086.286.287.286P, .8087, a ..NO87

Zásadní změny sady Visual Studio 2008

Compiler

  • 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_object

    • Perfmon

    • request_handler

    • soap_handler

    • soap_header

    • soap_method

    • tag_name

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_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í pomocí _HAS_ITERATOR_DEBUGGING definované (nahrazeno _ITERATOR_DEBUG_LEVEL po sadě Visual Studio 2010), aplikace se teď bude uplatňovat, když se iterátor pokusí zvýšit nebo dekrementovat přes hranice podkladového kontejneru.

  • Členová proměnná c třídy zásobníku je nyní deklarována chráněna. 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 číslicemi, než je volá , frac_digitsdo_get používá se k jejich spotřebě. do_get Teď po použití většiny frac_digits znaků přestane parsovat.

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 kódování a dekódování dat z atlenc.h a utility funkcí a tříd 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 knihovně importu. 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 můžete použít k minimálnímu #define ATL_MIN_CRT závislosti projektu ATL 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 kódování a dekódování dat z atlenc.h a utility funkcí a tříd 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 knihovně importu. To neovlivní kód, který staticky používá funkce. Ovlivní pouze kód, který tyto funkce používá dynamicky.

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í ovládacích prvků více ovládacích prvků v dialogovém okně MFC je narušeno, pokud je ovládací prvek MFC technologie ActiveX vložen do pořadí ovládacích prvků. Tato změna tento problém opraví.

    Můžete například vytvořit aplikaci dialogového okna MFC, která má ovládací prvek technologie ActiveX a několik ovládacích prvků pro úpravy. Umístěte ovládací prvek technologie 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 technologie ActiveX a potom tabulátorem. Před touto změnou se fokus přesune na ovládací prvek pro úpravy za ovládacím prvku technologie ActiveX namísto dalšího ovládacího prvku 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 GetMenuBarInfo Funkce 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, volejte 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 výstup stderr není k dispozici, 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 s jedním vláknem (libc.lib a libcd.lib) byly odebrány. Použijte knihovny CRT s více vlákny. 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. Pokud chcete povolit %n podpory, použijte _set_printf_count_output (viz _get_printf_count_outputtaké).

  • sprintf Nyní vytiskne záporné znaménko nuly se znaménkem znaménko

  • 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 byla odebrána. 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í ponechá errno nedotčený úspěch, jak je určeno standardem C.

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

  • Funkce podpory ovládacích slov s plovoucí desetinou čárkou jsou zastaralé pro aplikace zkompilované pomocí /CLR nebo /CLR:PURE. Ovlivněné funkce jsou _clear87, _clearfp. _control87_statusfp_controlfp_fpreset_status87 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é, non-const 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í se souborem 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 Rozbalení argumentů zástupných znaků.

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é inicializaci valarray namísto dynamického růstu jako vektor.

  • Ladicí iterátory: Aplikace vytvořené pomocí ladicí verze knihovny C-Runtime a které používají iterátory nesprávně, mohou začít zobrazovat kontrolní výrazy za běhu. Chcete-li tyto výrazy zakázat, je nutné definovat _HAS_ITERATOR_DEBUGGING (nahrazeno _ITERATOR_DEBUG_LEVEL po sadě Visual Studio 2010) na 0. Další informace naleznete v tématu Podpora iterátoru ladění

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

Compiler

  • 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 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<> se teď vyžaduje na místech, kde by kompilátor dříve znamenal (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 bez typu s plovoucí desetinou čárkou už nejsou povolené (Chyba kompilátoru C2993).

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

  • Názvy přátelských funkcí už nejsou zavedeny 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).

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

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

Viz také

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