Historia zmian języka Microsoft C/C++ 2003 – 2015
W tym artykule opisano wszystkie zmiany powodujące niezgodność z programu Visual Studio 2015 z powrotem do programu Visual Studio 2003, a w tym artykule terminy "nowe zachowanie" lub "teraz" odnoszą się do programu Visual Studio 2015 i nowszych. Terminy "stare zachowanie" i "przed" odnoszą się do programu Visual Studio 2013 i wcześniejszych wersji.
Aby uzyskać informacje o najnowszej wersji programu Visual Studio, zobacz Co nowego dla języka C++ w programie Visual Studio i ulepszeniach zgodności języka C++ w programie Visual Studio.
Uwaga
W programie Visual Studio 2015 i Visual Studio 2017 nie występują żadne zmiany powodujące niezgodność binarne.
Podczas uaktualniania do nowej wersji programu Visual Studio mogą wystąpić błędy kompilacji i/lub środowiska uruchomieniowego w kodzie, który został wcześniej skompilowany i uruchomiony poprawnie. Zmiany w nowej wersji, które powodują takie problemy, są znane jako zmiany powodujące niezgodność i zazwyczaj są wymagane przez modyfikacje w standardzie języka C++, sygnaturach funkcji lub układzie obiektów w pamięci.
Aby uniknąć błędów czasu wykonywania, które są trudne do wykrycia i zdiagnozowania, zalecamy, aby nigdy nie łączyć się statycznie z plikami binarnymi skompilowanymi przy użyciu innej wersji kompilatora. Ponadto, gdy uaktualniasz projekt EXE lub DLL, upewnij się, że uaktualniasz również biblioteki, z którymi się on łączy. Nie przekazuj typów biblioteki CRT (C Runtime) ani C++ Standard Library (C++ Standard Library) między plikami binarnymi, w tym bibliotekami DLL, skompilowanymi przy użyciu różnych wersji kompilatora. Aby uzyskać więcej informacji, zobacz Potencjalne błędy przekazywania obiektów CRT przez granice bibliotek DLL.
Nigdy nie należy pisać kodu, który zależy od określonego układu obiektu, który nie jest interfejsem COM ani obiektem ZASOB. Jeśli jednak piszesz taki kod, upewnij się, że działa po uaktualnieniu. Aby uzyskać więcej informacji, zobacz Przenośność w granicach ABI.
Ponadto ciągłe ulepszenia zgodności kompilatora mogą czasami zmieniać sposób, w jaki kompilator rozumie istniejący kod źródłowy. Na przykład możesz znaleźć nowe lub różne błędy podczas kompilacji, a nawet różnice behawioralne w kodzie, który został wcześniej skompilowany i wydawał się działać poprawnie. Chociaż te ulepszenia nie są zmianami powodującymi niezgodność, takimi jak te omówione w tym dokumencie, może być konieczne wprowadzenie zmian w kodzie źródłowym, aby rozwiązać następujące problemy:
Zmiany powodujące niezgodność biblioteki środowiska uruchomieniowego języka C (CRT)
Zmiany powodujące niezgodność standardowej biblioteki C++ i C++
Zmiany powodujące niezgodność środowiska uruchomieniowego współbieżności
Zmiany zgodności programu Visual Studio 2015
Biblioteka środowiska uruchomieniowego języka C (CRT)
Zmiany ogólne
Refaktoryzowane pliki binarne
Biblioteka CRT została refaktoryzowana w dwóch różnych plikach binarnych: universal CRT (ucrtbase), która zawiera większość standardowych funkcji i bibliotekę środowiska uruchomieniowego VC (vcruntime). Biblioteka vcruntime zawiera funkcje związane z kompilatorem, takie jak obsługa wyjątków i funkcje wewnętrzne. Jeśli używasz domyślnych ustawień projektu, ta zmiana nie ma wpływu na Ciebie, ponieważ konsolidator automatycznie używa nowych bibliotek domyślnych. Jeśli właściwość konsolidatora projektu ignoruj wszystkie biblioteki domyślne na Wartość Tak lub używasz
/NODEFAULTLIB
opcji konsolidatora w wierszu polecenia, musisz zaktualizować listę bibliotek (we właściwości Dodatkowe zależności), aby uwzględnić nowe, refaktoryzowane biblioteki. Zastąp starą bibliotekę CRT (libcmt.lib
,libcmtd.lib
,msvcrt.lib
,msvcrtd.lib
) równoważną refaktoryzowaną biblioteką. Dla każdej z dwóch refaktoryzowanych bibliotek istnieją wersje statyczne (lib) i dynamiczne (.dll) oraz wersje wydania (bez sufiksu) i debugowania (z sufiksem "d"). Wersje dynamiczne mają bibliotekę importu, z którą łączysz. Dwie refaktoryzowane biblioteki to Universal CRT, w szczególności ucrtbase.dll lub ucrtbase.lib, ucrtbased.dll lub ucrtbased.lib oraz biblioteka środowiska uruchomieniowego VC,libvcruntime.lib
wersja vcruntime.dll,libvcruntimed.lib
i wersja vcruntimed.dll. Wersja programu Visual Studio 2015 i Visual Studio 2017 to 140. Zobacz Funkcje biblioteki CRT.
<locale.h>
localeconv
Funkcja
localeconv
zadeklarowana w pliku locale.h działa teraz poprawnie po włączeniu ustawień regionalnych dla każdego wątku. W poprzednich wersjach biblioteki ta funkcja zwrócilconv
dane dla globalnych ustawień regionalnych, a nie ustawień regionalnych wątku.Jeśli używasz ustawień regionalnych dla każdego wątku
localeconv
, należy sprawdzić użycie elementu . Jeśli w kodzie przyjęto założenie, żelconv
zwrócone dane są przeznaczone dla globalnych ustawień regionalnych, należy je poprawić.
<math.h>
Przeciążenia biblioteki matematycznej w języku C++
W poprzednich wersjach
<math.h>
zdefiniowano niektóre, ale nie wszystkie przeciążenia języka C++ dla funkcji biblioteki matematycznej. Pozostałe przeciążenia znajdowały się w nagłówku<cmath>
. Kod, który został uwzględniony<math.h>
, może mieć problemy z rozpoznawaniem przeciążenia funkcji. Teraz przeciążenia języka C++ zostały usunięte z<math.h>
elementu i znajdują się tylko w pliku<cmath>
.Aby usunąć błędy, uwzględnij
<cmath>
deklaracje funkcji, które zostały usunięte z<math.h>
programu . Te funkcje zostały przeniesione:double abs(double)
ifloat abs(float)
double pow(double, int)
, ,float pow(float, float)
,float pow(float, int)
, ,long double pow(long double, long double)
long double pow(long double, int)
float
i wersje funkcji zmiennoprzecinkowych , ,atanh
asin
log1p
asinh
log2
atan
lrint
atan2
lround
cbrt
modf
ceil
nearbyint
copysign
nextafter
cos
nexttoward
cosh
remainder
erf
remquo
erfc
rint
exp
tgamma
fabs
tan
sqrt
sinh
sin
scalbn
scalbln
round
log10
log
llround
llrint
frexp
fmod
fmin
hypot
fma
ilogb
floor
tanh
expm1
ldexp
acosh
exp2
lgamma
fmax
fdim
iacos
long double
trunc
Jeśli masz kod używający
abs
typu zmiennoprzecinkowego, który zawiera<math.h>
tylko nagłówek, wersje zmiennoprzecinkowe nie będą już dostępne. Wywołanie jest teraz rozpoznawane jakoabs(int)
, nawet w przypadku argumentu zmiennoprzecinkowego, co powoduje błąd:warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of data
Poprawka tego ostrzeżenia polega na zastąpieniu wywołania
abs
zmiennoprzecinkowym wersjąabs
elementu , taką jakfabs
argument podwójny lubfabsf
argument zmiennoprzecinkowy, albo dołączenie<cmath>
nagłówka i kontynuowanie używania elementuabs
.Zgodność zmiennoprzecinkowa
Wprowadzono wiele zmian w bibliotece matematycznej w celu poprawy zgodności ze specyfikacjami IEEE-754 i C11 Załącznik F w odniesieniu do specjalnych danych wejściowych przypadków, takich jak NaN i niedociągnienia. Na przykład ciche dane wejściowe NaN, które były często traktowane jako błędy w poprzednich wersjach biblioteki, nie są już traktowane jako błędy. Zobacz IEEE 754 Standard i Załącznik F standardu C11.
Te zmiany nie spowodują błędów czasu kompilacji, ale mogą spowodować, że programy zachowują się inaczej i bardziej poprawnie zgodnie ze standardem.
FLT_ROUNDS
W programie Visual Studio 2013 makro FLT_ROUNDS zostało rozwinięte do wyrażenia stałego, co było nieprawidłowe, ponieważ tryb zaokrąglania można konfigurować w czasie wykonywania, na przykład przez wywołanie metody fesetround. Makro FLT_ROUNDS jest teraz dynamiczne i poprawnie odzwierciedla bieżący tryb zaokrąglania.
<new>
i <new.h>
new
idelete
W poprzednich wersjach biblioteki operator zdefiniowany przez implementację nowe i usunięte funkcje zostały wyeksportowane z biblioteki DLL biblioteki środowiska uruchomieniowego (na przykład msvcr120.dll). Te funkcje operatora są teraz zawsze statycznie połączone z plikami binarnymi, nawet w przypadku korzystania z biblioteki DLL biblioteki środowiska uruchomieniowego.
Nie jest to zmiana powodująca niezgodność dla natywnego lub mieszanego kodu (
/clr
), jednak w przypadku kodu skompilowanego jako /clr:pure ta zmiana może spowodować niepowodzenie kompilacji kodu. Jeśli skompilujesz kod jako/clr:pure
, może być konieczne dodanie#include <new>
lub#include <new.h>
obejście błędów kompilacji z powodu tej zmiany. Opcja/clr:pure
jest przestarzała w programie Visual Studio 2015 i nieobsługiwana w programie Visual Studio 2017. Kod, który musi być "czysty", powinien zostać przekierowany do języka C#.
<process.h>
_beginthread
i_beginthreadex
Funkcje
_beginthread
i_beginthreadex
przechowują teraz odwołanie do modułu, w którym procedura wątku jest definiowana przez czas trwania wątku. Pomaga to zapewnić, że moduły nie są zwalniane, dopóki wątek nie zostanie uruchomiony do ukończenia.
<stdarg.h>
va_start
typy referencyjne iPodczas kompilowania kodu C++ sprawdza teraz poprawność w czasie kompilacji,
va_start
że argument przekazany do niego nie jest typu odwołania. Argumenty typu odwołania są zabronione przez standard C++.
<stdio.h>
i <conio.h>
Rodzina funkcji printf i scanf jest teraz definiowana w tekście.
Definicje wszystkich
printf
funkcji iscanf
zostały przeniesione w tekście do<stdio.h>
nagłówków ,<conio.h>
i innych nagłówków CRT. Ta zmiana powodująca niezgodność prowadzi do błędu konsolidatora (LNK2019, nierozwiązanego symbolu zewnętrznego) dla wszystkich programów, które zadeklarowały te funkcje lokalnie bez uwzględniania odpowiednich nagłówków CRT. Jeśli to możliwe, należy zaktualizować kod tak, aby zawierał nagłówki CRT (czyli dodać#include <stdio.h>
) i funkcje wbudowane, ale jeśli nie chcesz modyfikować kodu w celu uwzględnienia tych plików nagłówków, alternatywnym rozwiązaniem jest dodanielegacy_stdio_definitions.lib
do danych wejściowych konsolidatora.Aby dodać tę bibliotekę do danych wejściowych konsolidatora w środowisku IDE, otwórz menu kontekstowe dla węzła projektu, wybierz pozycję Właściwości, a następnie w oknie dialogowym Właściwości projektu wybierz pozycję Konsolidator i edytuj dane wejściowe konsolidatora, aby dodać
legacy_stdio_definitions.lib
je do listy rozdzielanej średnikami.Jeśli projekt łączy się z bibliotekami statycznymi skompilowanymi w wersji programu Visual Studio wcześniej niż 2015, konsolidator może zgłosić nierozwiązany symbol zewnętrzny. Te błędy mogą odwoływać się do wewnętrznych definicji ,
_iob
_iob_func
lub powiązanych importów dla niektórych<stdio.h>
funkcji w postaci imp*. Firma Microsoft zaleca ponowne kompilowanie wszystkich bibliotek statycznych przy użyciu najnowszej wersji kompilatora i bibliotek języka C++ podczas uaktualniania projektu. Jeśli biblioteka jest biblioteką innej firmy, dla której źródło jest niedostępne, należy zażądać zaktualizowanego pliku binarnego od innej firmy lub hermetyzować użycie tej biblioteki w oddzielnej bibliotece DLL kompilowanej ze starszą wersją kompilatora i bibliotek.Ostrzeżenie
Jeśli łączysz się z zestawem Windows SDK 8.1 lub starszym, mogą wystąpić te nierozwiązane błędy symboli zewnętrznych. W takim przypadku należy rozwiązać ten błąd, dodając plik legacy_stdio_definitions.lib do danych wejściowych konsolidatora zgodnie z wcześniejszym opisem.
Aby rozwiązać problemy z nierozwiązanym błędami symboli, możesz spróbować użyć polecenia
dumpbin.exe
, aby sprawdzić symbole zdefiniowane w pliku binarnym. Wypróbuj następujący wiersz polecenia, aby wyświetlić symbole zdefiniowane w bibliotece.dumpbin.exe /LINKERMEMBER somelibrary.lib
pobiera i _getws
Funkcje pobierania i _getws zostały usunięte. Funkcja gets została usunięta z standardowej biblioteki języka C w języku C11, ponieważ nie można jej bezpiecznie używać. Funkcja _getws była rozszerzeniem firmy Microsoft, które było równoważne pobieraniu, ale dla szerokich ciągów. Jako alternatywy dla tych funkcji należy rozważyć użycie fgets, fgetws, gets_s i _getws_s.
_cgets i _cgetws
Funkcje _cgets i _cgetws zostały usunięte. Jako alternatywy dla tych funkcji należy rozważyć użycie _cgets_s i _cgetws_s.
Formatowanie nieskończoności i sieci NaN
W poprzednich wersjach wartości infinities i NaNs będą formatowane przy użyciu zestawu ciągów sentynel specyficznych dla MSVC.
Nieskończoność: 1.#INF
Quiet NaN: 1.#QNAN
Sygnał NaN: 1.#SNAN
NaN nieokreślony: 1.#IND
Każdy z tych formatów mógł być poprzedzony znakiem i mógł być sformatowany nieco inaczej w zależności od szerokości i dokładności pola (czasami z nietypowymi efektami, na przykład
printf("%.2f\n", INFINITY)
wydrukowałby 1,#J, ponieważ #INF będzie "zaokrąglany" do 2-cyfrowej precyzji). C99 wprowadził nowe wymagania dotyczące formatowania wartości infiniacji i sieci NaN. Implementacja MSVC jest teraz zgodna z tymi wymaganiami. Nowe ciągi są następujące:Nieskończoność: inf
Quiet NaN: nan
Signaling NaN: nan(snan)
NaN nieokreślony: nan(ind)
Każdy z nich może być poprzedzony znakiem. Jeśli jest używany specyfikator formatu wielkich liter (%F zamiast %f), ciągi są drukowane wielkimi literami (
INF
zamiast ), zgodnie zinf
wymaganiami.Funkcje scanf zostały zmodyfikowane, aby przeanalizować te nowe ciągi, więc te ciągi są teraz przekazywane w obie strony
printf
iscanf
.Formatowanie zmiennoprzecinkowe i analizowanie
Wprowadzono nowe algorytmy formatowania zmiennoprzecinkowego i analizowania w celu poprawy poprawności. Ta zmiana wpływa na rodziny funkcji printf i scanf oraz funkcje takie jak strtod.
Stare algorytmy formatowania będą generować tylko ograniczoną liczbę cyfr, a następnie wypełnić pozostałe miejsca dziesiętne z zera. Zazwyczaj mogą one generować ciągi, które byłyby zaokrąglone z powrotem do oryginalnej wartości zmiennoprzecinkowej, ale nie były doskonałe, jeśli potrzebujesz dokładnej wartości (lub najbliższej reprezentacji dziesiętnej). Nowe algorytmy formatowania generują tyle cyfr, ile jest wymaganych do reprezentowania wartości (lub wypełnienia określonej precyzji). Jako przykład poprawy; podczas drukowania dużej mocy dwóch elementów należy wziąć pod uwagę wyniki:
printf("%.0f\n", pow(2.0, 80))
Stare dane wyjściowe:
1208925819614629200000000
Nowe dane wyjściowe:
1208925819614629174706176
Stare algorytmy analizy rozważyłyby tylko 17 cyfr znaczących z ciągu wejściowego i odrzuciłyby resztę cyfr. Takie podejście jest wystarczające do wygenerowania bliskiego przybliżenia wartości reprezentowanej przez ciąg, a wynik jest zwykle bardzo zbliżony do poprawnie zaokrąglonego wyniku. Nowa implementacja uwzględnia wszystkie obecne cyfry i generuje poprawnie zaokrąglony wynik dla wszystkich danych wejściowych (do 768 cyfr długości). Ponadto te funkcje są teraz zgodne z trybem zaokrąglania (sterowane za pomocą fesetround). Jest to potencjalnie zmiana zachowania powodującego niezgodność, ponieważ te funkcje mogą zwracać różne wyniki. Nowe wyniki są zawsze bardziej poprawne niż stare wyniki.
Analizowanie szesnastkowe i nieskończoność/NaN
Algorytmy analizowania zmiennoprzecinkowego będą teraz analizować ciągi zmiennoprzecinkowe szesnastkowe (takie jak te generowane przez specyfikatory formatu wydruku %a i %A) oraz wszystkie ciągi nieskończoności i ciągów NaN generowanych przez
printf
funkcje, zgodnie z powyższym opisem.%A i %a zero dopełnienie
Specyfikatory formatu %a i %A formatowania formatuje liczbę zmiennoprzecinkową jako mantissa szesnastkowa i wykładnik binarny. W poprzednich wersjach
printf
funkcje nieprawidłowo tworzyły ciągi zero-pad. Na przykładprintf("%07.0a\n", 1.0)
można wydrukować 00x1p+0, gdzie powinien drukować 0x01p+0. Ta wada została naprawiona.%A i %a precyzja
Domyślna precyzja specyfikatorów formatu %A i %a wynosiła 6 w poprzednich wersjach biblioteki. Domyślna precyzja wynosi teraz 13 w celu zachowania zgodności ze standardem C.
Jest to zmiana zachowania środowiska uruchomieniowego w danych wyjściowych dowolnej funkcji, która używa ciągu formatu z %A lub %a. W starym zachowaniu dane wyjściowe używające specyfikatora %A mogą mieć wartość "1.1A2B3Cp+111". Teraz dane wyjściowe dla tej samej wartości to "1.1A2B3C4D5E6F7p+111". Aby uzyskać stare zachowanie, możesz określić precyzję, na przykład %.6A. Zobacz Specyfikacja precyzji.
Specyfikator %F
Specyfikator formatu/konwersji %F jest teraz obsługiwany. Jest ona funkcjonalnie równoważna specyfikatorowi formatu %f, z tą różnicą, że wartości infiniacji i sieci NaN są formatowane przy użyciu liter wielkich.
W poprzednich wersjach implementacja używana do analizowania F i N jako modyfikatorów długości. To zachowanie sięga epoki segmentowanych przestrzeni adresowych: te modyfikatory długości zostały użyte do wskazania odpowiednio daleko i blisko wskaźników, jak w %Fp lub %Ns. To zachowanie zostało usunięte. Jeśli plik %F zostanie napotkany, jest on teraz traktowany jako specyfikator formatu %F; Jeśli napotkano %N, jest on teraz traktowany jako nieprawidłowy parametr.
Formatowanie wykładnicze
Specyfikatory formatu %e i %E formatować liczbę zmiennoprzecinkową jako mantysę dziesiętną i wykładnik. Specyfikatory formatu %g i %G również formatuje liczby w tym formularzu w niektórych przypadkach. W poprzednich wersjach CRT zawsze generowałby ciągi z trzycyfrowymi wykładnikami. Na przykład
printf("%e\n", 1.0)
można wydrukować 1.0000000e+000, co było niepoprawne. C wymaga, aby jeśli wykładnik jest reprezentowany przy użyciu tylko jednej lub dwóch cyfr, tylko dwie cyfry mają być drukowane.W programie Visual Studio 2005 dodano globalny przełącznik zgodności: _set_output_format. Program może wywołać tę funkcję z argumentem _TWO_DIGIT_EXPONENT, aby umożliwić zgodne drukowanie wykładnicze. Domyślne zachowanie zostało zmienione na zgodny ze standardami tryb drukowania wykładniczego.
Walidacja ciągu formatu
W poprzednich wersjach
printf
funkcje iscanf
dyskretnie akceptują wiele nieprawidłowych ciągów formatu, czasami z nietypowymi efektami. Na przykład %hlhlhlhld będzie traktowany jako %d. Wszystkie nieprawidłowe ciągi formatu są teraz traktowane jako nieprawidłowe parametry.Walidacja ciągu trybu fopen
W poprzednich wersjach
fopen
rodzina funkcji dyskretnie zaakceptowała niektóre nieprawidłowe ciągi trybu, takie jakr+b+
. Nieprawidłowe ciągi trybu są teraz wykrywane i traktowane jako nieprawidłowe parametry.tryb _O_U8TEXT
Funkcja _setmode teraz prawidłowo zgłasza tryb otwartych strumieni in_O_U8TEXT. W poprzednich wersjach biblioteki raportowałby takie strumienie, jak otwierane w _O_WTEXT.
Jest to zmiana powodująca niezgodność, jeśli kod interpretuje tryb _O_WTEXT dla strumieni, gdzie kodowanie to UTF-8. Jeśli aplikacja nie obsługuje UTF_8, rozważ dodanie obsługi tego coraz bardziej typowego kodowania.
snprintf i vsnprintf
Funkcje snprintf i vsnprintf są teraz implementowane. Starszy kod często dostarczał wersje makr tych funkcji, ponieważ nie zostały zaimplementowane przez bibliotekę CRT, ale nie są już potrzebne w nowszych wersjach. Jeśli snprintf lub vsnprintf jest zdefiniowany jako makro przed dołączeniem
<stdio.h>
, kompilacja teraz kończy się niepowodzeniem z błędem wskazującym, gdzie zdefiniowano makro.Zwykle rozwiązaniem tego problemu jest usunięcie wszelkich deklaracji
snprintf
lubvsnprintf
w kodzie użytkownika.tmpnam generuje użyteczne nazwy plików
W poprzednich wersjach
tmpnam
funkcje itmpnam_s
wygenerowały nazwy plików w katalogu głównym dysku (na przykład \sd3c.). Te funkcje generują teraz ścieżki nazw plików do użytku w katalogu tymczasowym.Hermetyzacja PLIKÓW
W poprzednich wersjach pełny typ PLIKU został zdefiniowany publicznie w
<stdio.h>
pliku , więc kod użytkownika mógł uzyskać dostęp do pliku i zmodyfikować jego elementy wewnętrzne. Biblioteka została zmieniona w celu ukrycia szczegółów implementacji. W ramach tej zmiany plik zdefiniowany w pliku<stdio.h>
jest teraz nieprzezroczystym typem, a jego składowe są niedostępne spoza samego CRT._outp i _inp
Funkcje _outp, _outpw, _outpd, _inp, _inpw i _inpd zostały usunięte.
<stdlib.h>
, <malloc.h>
i <sys/stat.h>
strtof i wcstof
strtof
Nie można ustawićerrno
funkcji iwcstof
na ERANGE, gdy wartość nie była reprezentowana jako zmiennoprzecinkowa. Ten błąd był specyficzny dla tych dwóch funkcji; funkcjestrtod
,wcstod
,strtold
iwcstold
nie zostały naruszone. Ten problem został rozwiązany i jest zmianą powodującą niezgodność w czasie wykonywania.Funkcje alokacji wyrównane
W poprzednich wersjach wyrównane funkcje alokacji (
_aligned_malloc
,_aligned_offset_malloc
itp.) w trybie dyskretnym akceptują żądania dla bloku z wyrównaniem 0. Żądane wyrównanie musi być potęgą dwóch, która nie jest równa zero. Żądane wyrównanie wartości 0 jest teraz traktowane jako nieprawidłowy parametr. Ten problem został rozwiązany i jest zmianą powodującą niezgodność w czasie wykonywania.Funkcje stert
_heapadd
Funkcje ,_heapset
i_heapused
zostały usunięte. Te funkcje były niefunkcjonalne od czasu aktualizacji CRT w celu korzystania z sterty systemu Windows.smallheap
smallheap
Opcja łącza została usunięta. Zobacz Opcje łącza._Stat
Rodzina
_stat
funkcji jest używanaCreateFile
w programie Visual Studio 2015 zamiastFindFirstFile
w programie Visual Studio 2013 i starszych wersjach. Oznacza to, że_stat
na ścieżce kończącej się ukośnikiem kończy się powodzeniem, jeśli ścieżka odwołuje się do katalogu, w przeciwieństwie do wcześniejszego wystąpienia błędu funkcji z ustawioną wartościąerrno
ENOENT
.
<string.h>
wcstok
Podpis
wcstok
funkcji został zmieniony tak, aby był zgodny z wymaganiami standardu C. W poprzednich wersjach biblioteki podpis tej funkcji był następujący:wchar_t* wcstok(wchar_t*, wchar_t const*)
Użyto wewnętrznego kontekstu na wątek do śledzenia stanu między wywołaniami, tak jak w przypadku
strtok
elementu . Funkcja ma teraz podpiswchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**)
i wymaga od obiektu wywołującego przekazania kontekstu jako trzeciego argumentu do funkcji.Dodano nową
_wcstok
funkcję ze starym podpisem w celu ułatwienia przenoszenia. Podczas kompilowania kodu C++ istnieje również wbudowane przeciążeniewcstok
, które ma stary podpis. To przeciążenie jest deklarowane jako przestarzałe. W kodzie języka C można define_CRT_NON_CONFORMING_WCSTOK przyczynę_wcstok
użycia zamiastwcstok
elementu .
<time.h>
clock
W poprzednich wersjach
clock
funkcja została zaimplementowana przy użyciu interfejsu APIGetSystemTimeAsFileTime
systemu Windows . Dzięki tej implementacji funkcja zegara była wrażliwa na czas systemowy i w związku z tym niekoniecznie monotoniczna. Funkcja zegara została ponownie zaimplementowana pod względemQueryPerformanceCounter
i jest teraz monotoniczna.fstat i _utime
W poprzednich wersjach
_stat
funkcje ,fstat
i_utime
obsługują niepoprawnie czas letni. Przed programem Visual Studio 2013 wszystkie te funkcje nieprawidłowo dostosowywać czas standardowy tak, jakby były w czasie letnim.W programie Visual Studio 2013 problem został rozwiązany w
_stat
rodzinie funkcji, ale podobne problemy wfstat
rodzinach funkcji i_utime
nie zostały rozwiązane. Ta częściowa poprawka doprowadziła do problemów z powodu niespójności między funkcjami. Rodzinyfstat
funkcji i_utime
zostały naprawione, więc wszystkie te funkcje obsługują teraz czas letni prawidłowo i spójnie.asctime
W poprzednich wersjach funkcja będzie
asctime
zawierać jednocyfrowe dni z wiodącym zerem, na przykład:Fri Jun 06 08:00:00 2014
. Specyfikacja wymaga, aby takie dni zostały wypełnione spacją wiodącą, jak w plikuFri Jun 6 08:00:00 2014
. Ten problem został rozwiązany.strftime i wcsftime
Funkcje
strftime
iwcsftime
obsługują teraz specyfikatory formatu %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %u i %V. Ponadto modyfikatory E i O są analizowane, ale ignorowane.Specyfikator formatu %c jest określony jako tworzący "odpowiednią reprezentację daty i godziny" dla bieżących ustawień regionalnych. W ustawieniach regionalnych języka C ta reprezentacja musi być taka sama jak
%a %b %e %T %Y
, taka sama forma, jak w przypadkuasctime
elementu . W poprzednich wersjach specyfikator formatu %c niepoprawnie sformatowany przy użyciuMM/DD/YY HH:MM:SS
reprezentacji. Ten problem został rozwiązany.czas i TIME_UTC
Nagłówek
<time.h>
definiujetimespec
teraz typ itimespec_get
funkcję z C11 Standard. Ponadto makro TIME_UTC do użycia z funkcjątimespec_get
jest teraz zdefiniowane. Ta aktualizacja to zmiana powodująca niezgodność dla kodu, która zawiera definicję powodującą konflikt dla dowolnego z tych identyfikatorów.CLOCKS_PER_SEC
Makro CLOCKS_PER_SEC teraz rozszerza się na liczbę całkowitą typu
clock_t
, zgodnie z wymaganiami języka C.
Standardowa biblioteka C++
Aby włączyć nowe optymalizacje i kontrole debugowania, implementacja standardowej biblioteki C++ w Visual Studio celowo łamie zgodność binarną między wersjami. W związku z tym gdy używana jest standardowa biblioteka C++, pliki obiektowe i biblioteki statyczne, które są kompilowane przy użyciu różnych wersji, nie mogą być mieszane w jednym pliku binarnym (EXE lub DLL), a obiekty standardowej biblioteki C++ nie mogą być przekazywane między plikami binarnymi, które są kompilowane przy użyciu różnych wersji. Takie mieszanie powoduje błędy konsolidatora dotyczące niezgodności _MSC_VER. (_MSC_VER to makro, które zawiera wersję główną kompilatora — na przykład 1800 dla programu Visual Studio 2013). To sprawdzenie nie może wykryć mieszania bibliotek DLL i nie może wykryć mieszania, które obejmuje program Visual Studio 2008 lub starszy.
Standardowa biblioteka C++ zawiera pliki
Wprowadzono pewne zmiany w strukturze dołączania w nagłówkach biblioteki standardowej języka C++. Nagłówki standardowej biblioteki języka C++ mogą zawierać się nawzajem na nieokreślone sposoby. Ogólnie rzecz biorąc, należy napisać kod, tak aby dokładnie zawierał wszystkie nagłówki, których potrzebuje zgodnie ze standardem C++, i nie polegają na tym, które nagłówki standardowej biblioteki języka C++ zawierają inne nagłówki biblioteki standardowej języka C++. Dzięki temu kod jest przenośny w różnych wersjach i platformach. Co najmniej dwie zmiany nagłówka w programie Visual Studio 2015 wpływają na kod użytkownika.
<string>
Najpierw nie zawiera<iterator>
już elementu .<tuple>
Po drugie, teraz deklarujestd::array
bez uwzględniania wszystkich<array>
elementów , które mogą podzielić kod za pomocą następującej kombinacji konstrukcji kodu: kod ma zmienną o nazwie "array", i masz dyrektywę "using namespace std;" i dołączasz nagłówek biblioteki standardowej języka C++ (na przykład<functional>
), który zawiera<tuple>
element , który teraz deklarujestd::array
.steady_clock
steady_clock
Implementacja<chrono>
programu została zmieniona tak, aby spełniała standardowe wymagania języka C++ dotyczące niestabilności i monotoniczności.steady_clock
element jest teraz oparty naQueryPerformanceCounter
parametrze ihigh_resolution_clock
jest teraz definicją typów dla elementusteady_clock
. W związku z tym w programie Visual Studiosteady_clock::time_point
jest teraz definicjąchrono::time_point<steady_clock>
typu , jednak niekoniecznie jest to przypadek innych implementacji.alokatory i const
Teraz wymagamy porównania równości/nierówności alokatora, aby zaakceptować argumenty const po obu stronach. Jeśli alokatorzy definiują te operatory w następujący sposób,
bool operator==(const MyAlloc& other)
następnie należy je zaktualizować i zadeklarować jako elementy członkowskie const:
bool operator==(const MyAlloc& other) const
const, elementy
Standard C++ zawsze ma zabronione kontenery elementów const (takich jak
vector<const T>
lubset<const T>
). Program Visual Studio 2013 i wcześniejsze zaakceptował takie kontenery. W bieżącej wersji takie kontenery nie mogą być kompilowane.std::allocator::d eallocate
W programie Visual Studio 2013 i starszych
std::allocator::deallocate(p, n)
zignorowano argument przekazany dla n. Standardowa języka C++ zawsze wymagała, aby n musi być równe wartości przekazanej jako pierwszy argument wywołaniaallocate
metody , która zwróciła wartość p. Jednak w bieżącej wersji wartość n jest sprawdzana. Kod przekazujący argumenty dla n , które różnią się od tego, czego wymaga standard, może ulec awarii w czasie wykonywania.hash_map i hash_set
Niestandardowe pliki
<hash_map>
nagłówkowe i<hash_set>
są przestarzałe w programie Visual Studio 2015 i zostaną usunięte w przyszłej wersji. Użyj i<unordered_map>
<unordered_set>
zamiast tego.komparatory i operatory()
Kontenery asocjacyjne (
<map>
rodzina) wymagają teraz, aby ich komparatory miały operatory wywołań funkcji const-callable. Nie można skompilować następującego kodu w deklaracji klasy kompilatora:bool operator()(const X& a, const X& b)
Aby rozwiązać ten błąd, zmień deklarację funkcji na:
bool operator()(const X& a, const X& b) const
cechy typu
Stare nazwy cech typów z wcześniejszej wersji standardu roboczego języka C++ zostały usunięte. Zostały one zmienione w języku C++11 i zostały zaktualizowane do wartości języka C++11 w programie Visual Studio 2015. W poniższej tabeli przedstawiono stare i nowe nazwy.
Stara nazwa Nowa nazwa 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 i launch::sync policies
Niestandardowe
launch::any
zasady ilaunch::sync
zasady zostały usunięte. Zamiast tego dlalaunch::any
parametru użyj polecenialaunch:async | launch:deferred
. W przypadkulaunch::sync
programu użyj polecenialaunch::deferred
. Zobacz launch Enumeration (Wyliczenie uruchamiania).
MFC i ATL
Microsoft Foundation Classes (MFC)
Nie jest już uwzględniana w instalacji "Typowe" programu Visual Studio ze względu na jego duży rozmiar. Aby zainstalować MFC, wybierz opcję Instalacji niestandardowej w instalatorze programu Visual Studio 2015. Jeśli masz już zainstalowany program Visual Studio 2015, możesz zainstalować MFC, uruchamiając ponownie instalatora programu Visual Studio . Wybierz opcję Instalacja niestandardowa, a następnie wybierz pozycję Klasy programu Microsoft Foundation. Konfigurację programu Visual Studio można uruchomić z poziomu Panel sterowania kontrolki Programy i funkcje lub z nośnika instalacyjnego.
Pakiet redystrybucyjny Visual C++ wciąż zawiera tę bibliotekę.
Współbieżność środowiska wykonawczego
Zwracanie makra z pliku Windows.h powodujące konflikt ze współbieżnością::Context::Yield
Środowisko uruchomieniowe współbieżności używane
#undef
wcześniej do niezdefiniowania makra Yield w celu uniknięcia konfliktów między makrem Yield zdefiniowanym w systemie Windows.h iconcurrency::Context::Yield
funkcji. Zostało to#undef
usunięte, a dodano nową równoważną współbieżność wywołania interfejsu API, która nie powoduje konfliktu::Context::YieldExecution . Aby obejść konflikty z metodą Yield, możesz zaktualizować kod w celu wywołaniaYieldExecution
funkcji lub otoczyćYield
nazwę funkcji nawiasami w lokacjach wywołania, jak w poniższym przykładzie:(concurrency::Context::Yield)();
Ulepszenia zgodności kompilatora w programie Visual Studio 2015
Podczas uaktualniania kodu z poprzednich wersji mogą również wystąpić błędy kompilatora, które są spowodowane ulepszeniami zgodności w programie Visual Studio 2015. Te ulepszenia nie powodują przerwania zgodności binarnej z wcześniejszych wersji programu Visual Studio, ale mogą generować błędy kompilatora, w których żadne z nich nie były emitowane wcześniej. Aby uzyskać więcej informacji, zobacz Visual C++ What's New 2003 to 2015 (Co nowego w wersji od 2003 do 2015).
W programie Visual Studio 2015 ciągłe ulepszenia zgodności kompilatora mogą czasami zmieniać sposób zrozumienia istniejącego kodu źródłowego przez kompilator. W związku z tym podczas kompilacji mogą wystąpić nowe lub różne błędy, a nawet różnice behawioralne w kodzie, który wcześniej skompilował i wydawał się działać poprawnie.
Na szczęście te różnice nie mają wpływu na większość kodu źródłowego. Gdy kod źródłowy lub inne zmiany są potrzebne do rozwiązania tych różnic, poprawki wydają się być małe i proste. Dołączyliśmy wiele przykładów wcześniej akceptowalnego kodu źródłowego, które mogą wymagać zmiany (przed) i poprawek w celu ich poprawienia (po).
Chociaż te różnice mogą mieć wpływ na kod źródłowy lub inne artefakty kompilacji, nie mają wpływu na zgodność binarną między aktualizacjami wersji programu Visual Studio. Zmiana powodująca niezgodność jest poważniejsza i może mieć wpływ na zgodność binarną, ale tego rodzaju przerwy w zgodności binarnej występują tylko między głównymi wersjami programu Visual Studio, na przykład między programem Visual Studio 2013 i programem Visual Studio 2015. Aby uzyskać informacje na temat zmian powodujących niezgodność w programach Visual Studio 2013 i Visual Studio 2015, zobacz Visual Studio 2015 Conformance Changes (Zmiany zgodności programu Visual Studio 2015).
Ulepszenia zgodności w programie Visual Studio 2015
/Zc:forScope- opcja
Opcja
/Zc:forScope-
kompilatora jest przestarzała i zostanie usunięta w przyszłej wersji.Command line warning D9035: option 'Zc:forScope-' has been deprecated and will be removed in a future release
Zazwyczaj ta opcja została użyta w celu zezwolenia na niestandardowy kod, który używa zmiennych pętli po punkcie, w którym, zgodnie ze standardem, powinny one zniknąć z zakresu. To było konieczne tylko wtedy, gdy skompilowano z opcją
/Za
, ponieważ bez/Za
, użycie zmiennej for dla pętli po zakończeniu pętli jest zawsze dozwolone. Jeśli nie interesuje Cię zgodność ze standardami (na przykład jeśli kod nie jest przeznaczony do przenoszenia do innych kompilatorów), możesz wyłączyć/Za
opcję (lub ustawić właściwość Wyłącz rozszerzenia językowe na Nie). Jeśli dbasz o pisanie przenośnego, zgodnego ze standardami kodu, należy ponownie napisać kod, tak aby był zgodny ze standardem, przenosząc deklarację takich zmiennych do punktu poza pętlą.// 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
Opcja kompilatoraOpcja kompilatora
/Zg
(Generuj prototypy funkcji) nie jest już dostępna. Ta opcja kompilatora była wcześniej przestarzała.Nie można już uruchamiać testów jednostkowych za pomocą języka C++/interfejsu wiersza polecenia z mstest.exe. Zamiast tego użyj vstest.console.exe. Zobacz VSTest.Console.exe opcje wiersza polecenia.
modyfikowalne słowo kluczowe
Specyfikator
mutable
klasy magazynu nie jest już dozwolony w miejscach, w których wcześniej skompilowane bez błędu. Teraz kompilator zwraca błąd C2071 (nielegalna klasa magazynu). Zgodnie ze standardem specyfikatormutable
może być stosowany tylko do nazw składowych danych klasy i nie można ich stosować do nazw zadeklarowanych jako const lub static i nie można ich zastosować do składowych odwołań.Rozważmy na przykład następujący kod:
struct S { mutable int &r; };
Poprzednie wersje kompilatora zaakceptowały to, ale teraz kompilator daje następujący błąd:
error C2071: 'S::r': illegal storage class
Aby naprawić błąd, usuń nadmiarowe
mutable
słowo kluczowe.char_16_t i char32_t
Nie można już używać
char16_t
char32_t
aliasów ani jako aliasów w elemecietypedef
, ponieważ te typy są teraz traktowane jako wbudowane. Często zdarzało się, że użytkownicy i autorzy bibliotek definiująchar16_t
char32_t
odpowiednio i jako aliasyuint16_t
elementów iuint32_t
.#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; }
Aby zaktualizować kod, usuń
typedef
deklaracje i zmień nazwy innych identyfikatorów, które zderzają się z tymi nazwami.Parametry szablonu innego niż typ
Określony kod, który obejmuje parametry szablonu innego niż typ, jest teraz poprawnie sprawdzany pod kątem zgodności typów po podaniu jawnych argumentów szablonu. Na przykład poniższy kod skompilowany bez błędu w poprzednich wersjach programu 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>(); }
Bieżący kompilator poprawnie wyświetla błąd, ponieważ typ parametru szablonu nie jest zgodny z argumentem szablonu (parametr jest wskaźnikiem do elementu członkowskiego const, ale funkcja f jest inny niż 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'
Aby rozwiązać ten błąd w kodzie, upewnij się, że typ używanego argumentu szablonu pasuje do zadeklarowanego typu parametru szablonu.
__declspec(align)
Kompilator nie akceptuje
__declspec(align)
już funkcji. Ta konstrukcja była zawsze ignorowana, ale teraz generuje błąd kompilatora.error C3323: 'alignas' and '__declspec(align)' are not allowed on function declarations
Aby rozwiązać ten problem, usuń z
__declspec(align)
deklaracji funkcji. Ponieważ nie miało to żadnego wpływu, usunięcie go nie zmienia.Obsługa wyjątków
Istnieje kilka zmian obsługi wyjątków. Najpierw obiekty wyjątków muszą być kopiowalne lub wymienne. Poniższy kod skompilowany w programie Visual Studio 2013, ale nie jest kompilowany w programie Visual Studio 2015:
struct S { public: S(); private: S(const S &); }; int main() { throw S(); // error }
Problem polega na tym, że konstruktor kopiujący jest prywatny, więc nie można skopiować obiektu w normalny sposób obsługi wyjątku. To samo dotyczy, gdy konstruktor kopiujący jest zadeklarowany
explicit
.struct S { S(); explicit S(const S &); }; int main() { throw S(); // error }
Aby zaktualizować kod, upewnij się, że konstruktor kopiujący dla obiektu wyjątku nie jest
public
oznaczonyexplicit
jako .Przechwycenie wyjątku według wartości wymaga również skopiowania obiektu wyjątku. Poniższy kod skompilowany w programie Visual Studio 2013, ale nie jest kompilowany w programie Visual Studio 2015:
struct B { public: B(); private: B(const B &); }; struct D : public B {}; int main() { try { } catch (D d) // error { } }
Ten problem można rozwiązać, zmieniając typ parametru
catch
dla odwołania.catch (D& d) { }
Literały ciągu, po których następują makra
Kompilator obsługuje teraz literały zdefiniowane przez użytkownika. W związku z tym literały ciągów, po których następują makra bez żadnych interweniujących białych znaków, są interpretowane jako literały zdefiniowane przez użytkownika, co może powodować błędy lub nieoczekiwane wyniki. Na przykład w poprzednich kompilatorach następujący kod został pomyślnie skompilowany:
#define _x "there" char* func() { return "hello"_x; } int main() { char * p = func(); return 0; }
Kompilator zinterpretował ten kod jako literał ciągu "hello", po którym następuje makro, które zostało rozwinięte w "tam", a następnie dwa literały ciągu zostały łączone w jeden. W programie Visual Studio 2015 kompilator interpretuje tę sekwencję jako literał zdefiniowany przez użytkownika, ale ponieważ nie zdefiniowano pasującego literału
_x
zdefiniowanego przez użytkownika, zwraca błąd.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?
Aby rozwiązać ten problem, dodaj spację między literałem ciągu a makrem.
Sąsiadujące literały ciągu
Podobnie jak poprzednio, ze względu na powiązane zmiany w analizowaniu ciągów, sąsiadujące literały ciągu (szerokie lub wąskie literały ciągu) bez żadnych białych znaków zostały zinterpretowane jako pojedynczy połączony ciąg w poprzednich wersjach Visaul C++. W programie Visual Studio 2015 należy teraz dodać biały znak między dwoma ciągami. Na przykład należy zmienić następujący kod:
char * str = "abc""def";
Aby rozwiązać ten problem, dodaj spację między dwoma ciągami:
char * str = "abc" "def";
Umieszczanie nowych i usuwanie
Wprowadzono zmianę operatora
delete
w celu zapewnienia zgodności z standardem C++14. Szczegółowe informacje o zmianach standardów można znaleźć w artykule C++ Size Deallocation (Alokacja rozmiaru języka C++). Zmiany dodają postać operatora globalnegodelete
, który przyjmuje parametr rozmiaru. Zmiana powodująca niezgodność polega na tym, że jeśli wcześniej używano operatoradelete
z tym samym podpisem (aby odpowiadać nowemu operatorowi umieszczania), zostanie wyświetlony błąd kompilatora (C2956, który występuje w momencie użycia nowego umieszczania, ponieważ jest to pozycja w kodzie, w którym kompilator próbuje zidentyfikować odpowiedni operator dopasowaniadelete
).Funkcja
void operator delete(void *, size_t)
była operatorem usuwania umieszczania odpowiadającym nowej funkcjivoid * operator new(size_t, size_t)
umieszczania w języku C++11. W przypadku cofnięcia przydziału rozmiaru języka C++14 ta funkcja usuwania jest teraz zwykłą funkcją cofania transakcji (operator globalnydelete
). Standard wymaga, aby jeśli użycie funkcji umieszczania nowego wyszukuje odpowiednią funkcję usuwania i znajduje zwykłą funkcję cofania transakcji, program jest źle sformułowany.Załóżmy na przykład, że kod definiuje zarówno umieszczenie nowego, jak i usunięcie umieszczania:
void * operator new(std::size_t, std::size_t); void operator delete(void*, std::size_t) noexcept;
Problem występuje z powodu dopasowania podpisów funkcji między zdefiniowanym operatorem usuwania umieszczania i nowym operatorem rozmiaru
delete
globalnego. Zastanów się, czy można użyć innego typu niżsize_t
w przypadku dowolnego umieszczania nowych operatorów idelete
. Typ obiektusize_t
typedef
jest zależny od kompilatora. Jest on elementemtypedef
forunsigned int
w środowisku MSVC. Dobrym rozwiązaniem jest użycie wyliczonego typu, takiego jak ten:enum class my_type : size_t {};
Następnie zmień definicję umieszczania nowego i
delete
użyj tego typu jako drugiego argumentusize_t
zamiast . Należy również zaktualizować wywołania, aby umieścić nowe, aby przekazać nowy typ (na przykład za pomocą poleceniastatic_cast<my_type>
, aby przekonwertować wartość z liczby całkowitej) i zaktualizować definicjęnew
idelete
rzutować z powrotem do typu liczby całkowitej. Nie musisz używać elementuenum
dla tego elementu; typ klasy z elementemsize_t
członkowskim również będzie działać.Alternatywną rozwiązaniem jest możliwość całkowitego wyeliminowania umieszczania. Jeśli kod używa funkcji umieszczania nowego w celu zaimplementowania puli pamięci, w której argument umieszczania jest rozmiarem przydzielonego lub usuniętego obiektu, rozmiar funkcji cofania może być odpowiedni do zastąpienia własnego niestandardowego kodu puli pamięci i można pozbyć się funkcji umieszczania i po prostu użyć własnego operatora dwóch argumentów
delete
zamiast funkcji umieszczania.Jeśli nie chcesz natychmiast aktualizować kodu, możesz przywrócić stare zachowanie przy użyciu opcji
/Zc:sizedDealloc-
kompilatora . Jeśli używasz tej opcji, funkcje usuwania dwóch argumentów nie istnieją i nie spowodują konfliktu z operatorem usuwania umieszczania.Składowe danych unii
Składowe danych związków nie mogą już mieć typów odwołań. Poniższy kod został pomyślnie skompilowany w programie Visual Studio 2013, ale generuje błąd w programie Visual Studio 2015.
union U1 { const int i; }; union U2 { int & i; }; union U3 { struct { int & i; }; };
Powyższy kod generuje następujące błędy:
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
Aby rozwiązać ten problem, zmień typy odwołań na wskaźnik lub wartość. Zmiana typu na wskaźnik wymaga zmian w kodzie, który używa pola unii. Zmiana kodu na wartość spowoduje zmianę danych przechowywanych w unii, co wpływa na inne pola, ponieważ pola w typach unii współdzielą tę samą pamięć. W zależności od rozmiaru wartości może również zmienić rozmiar unii.
Anonimowe związki zawodowe są teraz bardziej zgodne ze standardem. Poprzednie wersje kompilatora wygenerowały jawny konstruktor i destruktor dla anonimowych związków. Te funkcje generowane przez kompilator są usuwane w programie Visual Studio 2015.
struct S { S(); }; union { struct { S s; }; } u; // C2280
Powyższy kod generuje następujący błąd w programie Visual Studio 2015:
error C2280: '<unnamed-type-u>::<unnamed-type-u>(void)': attempting to reference a deleted function note: compiler has generated '<unnamed-type-u>::<unnamed-type-u>' here
Aby rozwiązać ten problem, podaj własne definicje konstruktora i/lub destruktora.
struct S { // Provide a default constructor by adding an empty function body. S() {} }; union { struct { S s; }; } u;
Związki z anonimowymi strukturami
Aby zachować zgodność ze standardem, zachowanie środowiska uruchomieniowego zmieniło się dla elementów członkowskich struktur anonimowych w związkach. Konstruktor dla anonimowych składowych struktury w unii nie jest już niejawnie wywoływany po utworzeniu takiego związku. Ponadto destruktor anonimowych składowych struktury w unii nie jest już niejawnie wywoływany, gdy związek wykracza poza zakres. Rozważmy następujący kod, w którym unia U zawiera anonimową strukturę zawierającą nazwaną strukturę składową S, która ma destruktora.
#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; }
W programie Visual Studio 2013 konstruktor dla języka S jest wywoływany podczas tworzenia unii, a destruktor dla języka S jest wywoływany, gdy stos funkcji f jest czyszczony. Jednak w programie Visual Studio 2015 konstruktor i destruktor nie są wywoływane. Kompilator wyświetla ostrzeżenie dotyczące tej zmiany zachowania.
warning C4587: 'U::s': behavior change: constructor is no longer implicitly calledwarning C4588: 'U::s': behavior change: destructor is no longer implicitly called
Aby przywrócić oryginalne zachowanie, nadaj strukturze anonimowej nazwę. Zachowanie środowiska uruchomieniowego struktur innych niż anonimowe jest takie samo, niezależnie od wersji kompilatora.
#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; }
Alternatywnie spróbuj przenieść konstruktor i kod destruktora do nowych funkcji i dodać wywołania do tych funkcji z konstruktora i destruktora dla unii.
#include <stdio.h> struct S { void Create() { printf("Creating S.\n"); } void Destroy() { printf("Destroying S\n"); } }; union U { struct { S s; }; U() { s.Create(); } ~U() { s.Destroy(); } }; void f() { U u; } int main() { f(); char s[1024]; printf("Press any key.\n"); gets_s(s); return 0; }
Rozpoznawanie szablonu
Wprowadzono zmiany w rozpoznawaniu nazw dla szablonów. W języku C++, biorąc pod uwagę kandydatów do rozpoznawania nazwy, może się okazać, że co najmniej jedna nazwa uwzględniana jako potencjalne dopasowania powoduje utworzenie nieprawidłowego wystąpienia szablonu. Te nieprawidłowe wystąpienia zwykle nie powodują błędów kompilatora, zasady znanej jako SFINAE (Niepowodzenie podstawiania nie jest błędem).
Jeśli teraz sfINAE wymaga, aby kompilator tworzył wystąpienie specjalizacji szablonu klasy, wszelkie błędy występujące podczas tego procesu to błędy kompilatora. W poprzednich wersjach kompilator zignorowałby takie błędy. Rozważmy na przykład następujący kod:
#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); }
Jeśli kompilujesz przy użyciu bieżącego kompilatora, wystąpi następujący błąd:
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 ]
Wynika to z faktu, że w momencie pierwszego wywołania is_base_of klasa
D
nie została jeszcze zdefiniowana.W takim przypadku poprawka polega na tym, aby nie używać takich cech typu do momentu zdefiniowania klasy. Jeśli przeniesiesz definicje
B
iD
na początek pliku kodu, błąd zostanie rozwiązany. Jeśli definicje znajdują się w plikach nagłówków, sprawdź kolejność instrukcji include dla plików nagłówków, aby upewnić się, że wszystkie definicje klas są kompilowane przed użyciem problematycznych szablonów.Konstruktory kopii
W programach Visual Studio 2013 i Visual Studio 2015 kompilator generuje konstruktor kopii dla klasy, jeśli ta klasa ma konstruktor przenoszenia zdefiniowany przez użytkownika, ale nie zdefiniowano konstruktora kopiowania zdefiniowanego przez użytkownika. W usłudze Dev14 ten niejawnie wygenerowany konstruktor kopiowania jest również oznaczony jako "= delete".
parametr main zadeklarowany jako extern "C" wymaga teraz typu zwracanego.
Poniższy kod generuje teraz kod C4430.
extern "C" __cdecl main(){} // C4430
Aby naprawić błąd, dodaj zwracany typ:
extern "C" int __cdecl main(){} // OK
typename nie jest dozwolona w inicjatorze składowym
Poniższy kod tworzy teraz kod C2059:
template<typename T> struct S1 : public T::type { S1() : typename T::type() // C2059 { } }; struct S2 { typedef S2 type; }; S1<S2> s;
Aby naprawić błąd, usuń element
typename
z inicjatora:S1() : T::type() // OK ...
Klasa magazynu w przypadku jawnych specjalizacji jest ignorowana.
W poniższym kodzie specyfikator klasy magazynu statycznego jest ignorowany
template <typename T> void myfunc(T h) { } template<> static void myfunc(double h) // static is ignored { }
Stała używana w static_assert wewnątrz szablonu klasy zawsze kończy się niepowodzeniem.
Poniższy kod powoduje, że polecenie zawsze kończy się niepowodzeniem
static_assert
:template <size_t some_value> struct S1 { static_assert(false, "default not valid"); // always invoked }; //other partial specializations here
Aby obejść ten problem, zawijaj wartość w obiekcie
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
Reguły wymuszane dla deklaracji przesyłania dalej. (Dotyczy tylko C.)
Poniższy kod generuje teraz kod C2065:
struct token_s; typedef int BOOL; typedef int INT; typedef int(*PFNTERM)(PTOKEN, BOOL, INT); // C2065: 'PTOKEN' : undeclared identifier
Aby rozwiązać ten problem, dodaj odpowiednie deklaracje przekazywania:
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);
Bardziej spójne wymuszanie typów wskaźników funkcji
Poniższy kod tworzy teraz kod C2197:
typedef int(*F1)(int); typedef int(*F2)(int, int); void func(F1 f, int v1, int v2) { f(v1, v2); // C2197 }
Niejednoznaczne wywołania funkcji przeciążonych
Poniższy kod tworzy teraz kod C266: "N::bind": niejednoznaczne wywołanie funkcji przeciążonej
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 } };
Aby rozwiązać ten problem, możesz w pełni zakwalifikować wywołanie do
bind: N::bind(...)
. Jeśli jednak ta zmiana jest manifestem za pomocą niezdecydowanego identyfikatora (C2065), może być konieczne naprawienie tej zmiany za pomocąusing
deklaracji.Ten wzorzec występuje często w przypadku języka ComPtr i innych typów w
Microsoft::WRL
przestrzeni nazw.Naprawianie nieprawidłowego adresu
Poniższy kod tworzy teraz kod C2440: '=': nie można przekonwertować z "typu *" na "typ". Aby naprawić błąd, zmień &(typ) na (typ) i (&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()); }
Literał ciągu jest tablicą stałą
Poniższy kod generuje teraz kod C2664: "void f(void )': nie można przekonwertować argumentu 1 z "const char ()[2]" na "void *"
void f(void *); void h(void) { f(&__FUNCTION__); void *p = &""; }
Aby rozwiązać ten problem, zmień typ parametru funkcji na
const void*
, lub zmień treśćh
elementu , aby wyglądała następująco:void h(void) { char name[] = __FUNCTION__; f( name); void *p = &""; }
Ciągi UDL języka C++11
Poniższy kod generuje teraz błąd C3688: nieprawidłowy sufiks literału "L"; Nie można odnaleźć operatora literału lub szablonu operatora literału "operator"L"
#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"); }
Aby naprawić błąd, zmień kod, aby dodać spację:
#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"); }
W powyższym
MACRO
przykładzie nie jest już analizowany jako dwa tokeny (ciąg, po którym następuje makro). Teraz jest ona analizowana jako pojedynczy token UDL. To samo dotyczy L""L", który został przeanalizowany wcześniej jako L"" i L"", a teraz jest analizowany jako L""L i "".Reguły łączenia ciągów zostały również wprowadzone zgodnie ze standardem, co oznacza, że L"a" "b" jest odpowiednikiem L"ab". Poprzednie wersje programu Visual Studio nie akceptowały łączenia ciągów o innej szerokości znaków.
Usunięto pusty znak C++11
Poniższy kod generuje teraz błąd C2137: stała pustego znaku
bool check(wchar_t c){ return c == L''; //implicit null character }
Aby naprawić błąd, zmień kod, aby jawnie ustawić wartość null:
bool check(wchar_t c){ return c == L'\0'; }
Wyjątki MFC nie mogą być przechwytywane według wartości, ponieważ nie można ich kopiować
Następujący kod w aplikacji MFC powoduje teraz błąd C2316: "D": nie można przechwycić, ponieważ destruktor i/lub konstruktor kopiowania są niedostępne lub usunięte
struct B { public: B(); private: B(const B &); }; struct D : public B { }; int main() { try { } catch (D) // C2316 { } }
Aby naprawić kod, można zmienić blok catch na
catch (const D &)
, ale lepszym rozwiązaniem jest zwykle użycie makr TRY/CATCH MFC.alignof
jest teraz słowem kluczowymPoniższy kod generuje teraz błąd C2332: "class": brak nazwy tagu. Aby naprawić kod, musisz zmienić nazwę klasy lub, jeśli klasa wykonuje tę samą pracę co
alignof
, po prostu zastąp klasę nowym słowem kluczowym.class alignof{}
constexpr
jest teraz słowem kluczowymPoniższy kod generuje teraz błąd C2059: błąd składni: ")". Aby naprawić kod, należy zmienić nazwę dowolnej funkcji lub nazw zmiennych, które są nazywane
constexpr
.int constexpr() {return 1;}
Typy wymienne nie mogą być const
Gdy funkcja zwraca typ, który ma zostać przeniesiony, jego zwracany typ nie powinien mieć wartości
const
.Usunięte konstruktory kopii
Poniższy kod tworzy teraz kod C2280 "S::S(S(S &&)": próbuje odwołać się do usuniętej funkcji:
struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = S(2, 3); //C2280
Aby rozwiązać ten problem, użyj bezpośredniej inicjalizacji dla elementu
S2
:struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = {2,3}; //OK
Konwersja na wskaźnik funkcji wygenerowany tylko wtedy, gdy nie przechwytywanie lambda
Poniższy kod generuje kod C2664 w programie Visual Studio 2015.
void func(int(*)(int)) {} int main() { func([=](int val) { return val; }); }
Aby naprawić błąd, usuń element
=
z listy przechwytywania.Niejednoznaczne wywołania obejmujące operatory konwersji
Poniższy kod generuje teraz błąd C2440: "rzutowanie typu": nie można przekonwertować z "S2" na "S1":
struct S1 { S1(int); }; struct S2 { operator S1(); operator int(); }; void f(S2 s2) { (S1)s2; }
Aby naprawić błąd, jawnie wywołaj operatora konwersji:
void f(S2 s2) { //Explicitly call the conversion operator s2.operator S1(); // Or S1((int)s2); }
Następujący kod generuje teraz błąd C2593: "operator =" jest niejednoznaczny:
struct S1 {}; struct S2 { operator S1&(); operator S1() const; }; void f(S1 *p, S2 s) { *p = s; }
Aby naprawić błąd, jawnie wywołaj operatora konwersji:
void f(S1 *p, S2 s) { *p = s.operator S1&(); }
Naprawiono nieprawidłową inicjację kopiowania w inicjalizacji niestacjonalizowanej składowej danych (NSDMI)
Następujący kod generuje teraz błąd C2664: "S1::S1(S1 &&)": nie można przekonwertować argumentu 1 z "bool" na "const S1 &":
struct S1 { explicit S1(bool); }; struct S2 { S1 s2 = true; // error };
Aby naprawić błąd, użyj bezpośredniej inicjalizacji:
struct S2 { S1 s1{true}; // OK };
Uzyskiwanie dostępu do konstruktorów wewnątrz instrukcji decltype
Poniższy kod generuje teraz kod C2248: "S::S": nie można uzyskać dostępu do prywatnego elementu członkowskiego zadeklarowanej w klasie "S":
class S { S(); public: int i; }; class S2 { auto f() -> decltype(S().i); };
Aby rozwiązać ten problem, dodaj deklarację znajomego elementu w
S2
pliku :S
class S { S(); friend class S2; // Make S2 a friend public: int i; };
Domyślny obiekt ctor lambda jest niejawnie usuwany
Poniższy kod generuje teraz błąd C3497: nie można skonstruować wystąpienia lambda:
void func(){ auto lambda = [](){}; decltype(lambda) other; }
Aby naprawić błąd, usuń konieczność wywołania domyślnego konstruktora. Jeśli lambda nic nie przechwytuje, można go rzutować do wskaźnika funkcji.
Lambdas z usuniętym operatorem przypisania
Poniższy kod generuje teraz błąd 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); }
Aby naprawić błąd, zastąp element lambda klasą functor lub usuń konieczność użycia operatora przypisania.
Próba przeniesienia obiektu z usuniętym konstruktorem kopiowania
Poniższy kod generuje teraz błąd C2280: "moveable::moveable(const moveable &)": próba odwołania się do usuniętej funkcji
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; };
Aby naprawić błąd, użyj
std::move
zamiast tego:S(moveable && m) : m_m(std::move(m))
Klasa lokalna nie może odwoływać się do innych klas lokalnych zdefiniowanych w dalszej części tej samej funkcji
Poniższy kod generuje teraz błąd C2079: "s" używa niezdefiniowanej struktury "main::S2"
int main() { struct S2; struct S1 { void f() { S2 s; } }; struct S2 {}; }
Aby naprawić błąd, przenieś definicję
S2
elementu :int main() { struct S2 { //moved up }; struct S1 { void f() { S2 s; } }; }
Nie można wywołać chronionego ctora podstawowego w treści pochodnego obiektu ctor.
Następujący kod generuje teraz błąd C2248: "S1::S1": nie można uzyskać dostępu do chronionej składowej zadeklarowanej w klasie "S1"
struct S1 { protected: S1(); }; struct S2 : public S1 { S2() { S1(); } };
Aby naprawić błąd, usuń
S2
wywołanieS1()
metody z konstruktora i w razie potrzeby umieść je w innej funkcji.{} zapobiega konwersji na wskaźnik
Poniższy kod generuje teraz kod C2439 "S::p": nie można zainicjować elementu członkowskiego
struct S { S() : p({ 0 }) {} void *p; };
Aby rozwiązać ten problem, usuń nawiasy klamrowe z wokół
0
polecenia lub zamiast tego użyj polecenianullptr
, jak pokazano w tym przykładzie:struct S { S() : p(nullptr) {} void *p; };
Nieprawidłowa definicja makra i użycie z nawiasami
Poniższy przykład generuje teraz błąd C2008: ";": nieoczekiwany w definicji makr
#define A; //cause of error struct S { A(); // error };
Aby rozwiązać ten problem, zmień górną linię na
#define A();
Następujący kod generuje błąd C2059: błąd składni: ")"
//notice the space after 'A' #define A () ; struct S { A(); };
Aby naprawić kod, usuń spację między elementami A i ().
Następujący kod generuje błąd C2091: funkcja zwraca funkcję:
#define DECLARE void f() struct S { DECLARE(); };
Aby naprawić błąd, usuń nawiasy po zadeklarowaniu w S:
DECLARE;
.Następujący kod generuje błąd C2062: nieoczekiwany typ "int"
#define A (int) struct S { A a; };
Aby rozwiązać ten problem, zdefiniuj następujące elementy
A
:#define A int
Dodatkowe parensy w deklaracjach
Następujący kod generuje błąd C2062: nieoczekiwany typ "int"
struct S { int i; (int)j; };
Aby naprawić błąd, usuń nawiasy wokół
j
elementu . Jeśli nawiasy są potrzebne do jasności, użyj elementutypedef
.Konstruktory generowane przez kompilator i __declspec (novtable)
W programie Visual Studio 2015 istnieje zwiększone prawdopodobieństwo, że konstruktory wbudowane w kompilatorze klas abstrakcyjnych z wirtualnymi klasami bazowymi mogą uwidocznić nieprawidłowe użycie
__declspec(novtable)
funkcji w przypadku użycia w połączeniu z elementem__declspec(dllimport)
.auto wymaga pojedynczego wyrażenia w inicjowaniu listy bezpośredniej
Poniższy kod generuje teraz błąd C3518: "testPositions": w kontekście inicjowania listy bezpośredniej typ "auto" można odwieść tylko z pojedynczego wyrażenia inicjatora
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} };
Aby naprawić błąd, jedną z możliwości jest zainicjowanie
testPositions
w następujący sposób: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} };
Sprawdzanie typów a wskaźniki do typów dla is_convertible
Poniższy kod powoduje teraz niepowodzenie asercji statycznej.
struct B1 { private: B1(const B1 &); }; struct B2 : public B1 {}; struct D : public B2 {}; static_assert(std::is_convertible<D, B2>::value, "fail");
Aby naprawić błąd, zmień element
static_assert
tak, aby porównał wskaźniki z elementamiD
iB2
:static_assert(std::is_convertible<D*, B2*>::value, "fail");
deklaracje __declspec (novtable) muszą być spójne
__declspec
deklaracje muszą być spójne we wszystkich bibliotekach. Poniższy kod spowoduje teraz wygenerowanie naruszenia reguły jednej definicji (ODR)://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;
Ulepszenia zgodności w aktualizacji Update 1
Prywatne wirtualne klasy bazowe i dziedziczenie pośrednie
Poprzednie wersje kompilatora zezwalały klasie pochodnej na wywoływanie funkcji składowych jej pośrednio pochodnych
private virtual
klas bazowych. To stare zachowanie było nieprawidłowe i nie jest zgodne ze standardem C++. Kompilator nie akceptuje już kodu napisanego w ten sposób i w rezultacie wystawia błąd kompilatora C2280.error C2280: 'void *S3::__delDtor(unsigned int)': attempting to reference a deleted function
Przykład (przed)
class base { protected: base(); ~base(); }; class middle : private virtual base {}; class top : public virtual middle {}; void destroy(top *p) { delete p; // }
Przykład (po)
class base; // as above class middle : protected virtual base {}; class top : public virtual middle {}; void destroy(top *p) { delete p; }
- lub -
class base; // as above class middle : private virtual base {}; class top : public virtual middle, private virtual bottom {}; void destroy(top *p) { delete p; }
Przeciążony operator new and operator delete
Poprzednie wersje kompilatora zezwalały na usunięcie operatora innego niż składowe nowego i innego niż składowe jako statyczne i zadeklarowane w przestrzeniach nazw innych niż globalna przestrzeń nazw. To stare zachowanie spowodowało ryzyko, że program nie będzie wywoływać implementacji operatora lub
delete
zamierzonejnew
przez programistę, co spowodowało dyskretne złe zachowanie środowiska uruchomieniowego. Kompilator nie akceptuje już kodu napisanego w ten sposób i zamiast tego wystawia błąd kompilatora 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.
Przykład (przed)
static inline void * __cdecl operator new(size_t cb, const std::nothrow_t&) // error C2323
Przykład (po)
void * __cdecl operator new(size_t cb, const std::nothrow_t&) // removed 'static inline'
Ponadto, mimo że kompilator nie daje określonej diagnostyki, operator
new
wbudowany jest uznawany za źle sformułowany.Wywoływanie metody " operator type()" (konwersja zdefiniowana przez użytkownika) w typach innych niż klasy
Poprzednie wersje kompilatora zezwalały na wywoływanie typów nieklasowych "operator type()" przy dyskretnym ignorowaniu. To stare zachowanie spowodowało ryzyko dyskretnego generowania nieprawidłowego kodu, co spowodowało nieprzewidywalne zachowanie środowiska uruchomieniowego. Kompilator nie akceptuje już kodu napisanego w ten sposób i zamiast tego wystawia błąd kompilatora C2228.
error C2228: left of '.operator type' must have class/struct/union
Przykład (przed)
typedef int index_t; void bounds_check(index_t index); void login(int column) { bounds_check(column.operator index_t()); // error C2228 }
Przykład (po)
typedef int index_t; void bounds_check(index_t index); void login(int column) { bounds_check(column); // removed cast to 'index_t', 'index_t' is an alias of 'int' }
Nadmiarowa nazwa typu w specyfikatorach typów opracowanych
Poprzednie wersje kompilatora dozwolone
typename
w opracowanym specyfikatorze typu, ale kod napisany w ten sposób jest semantycznie niepoprawny. Kompilator nie akceptuje już kodu napisanego w ten sposób i zamiast tego wystawia błąd kompilatora C3406.error C3406: 'typename' cannot be used in an elaborated type specifier
Przykład (przed)
template <typename class T> class container;
Przykład (po)
template <class T> // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case class container;
Potrącenie typów tablic z listy inicjatorów
Poprzednie wersje kompilatora nie obsługiwały odliczania typów tablic z listy inicjatorów. Kompilator obsługuje teraz tę formę potrącenia typu, a w związku z tym wywołania szablonów funkcji przy użyciu list inicjatora mogą być teraz niejednoznaczne lub inne przeciążenie może zostać wybrane niż w poprzednich wersjach kompilatora. Aby rozwiązać te problemy, program musi teraz jawnie określić przeciążenie przeznaczone przez programistę.
Gdy to nowe zachowanie powoduje, że rozwiązanie przeciążenia uwzględnia dodatkowego kandydata, który jest równie dobry jak kandydat historyczny, wywołanie staje się niejednoznaczne, a w rezultacie błąd kompilatora problemów kompilatora C2668.
error C2668: 'function' : ambiguous call to overloaded function.
Przykład 1: Niejednoznaczne wywołanie funkcji przeciążonej (przed)
// 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 }
Przykład 1: niejednoznaczne wywołanie przeciążonej funkcji (po)
template < typename... Args> void f(int, Args...); // template < int N, typename... Args> void f(const int(&)[N], Args...); int main() { // To call f(int, Args...) when there is just one expression in the initializer list, remove the braces from it. f(3); }
Gdy to nowe zachowanie powoduje przeciążenie rozpoznawania, aby rozważyć dodatkowego kandydata, który jest lepszym dopasowaniem niż historyczny kandydat, wywołanie rozwiązuje się jednoznacznie z nowym kandydatem, powodując zmianę zachowania programu, która prawdopodobnie różni się od zamierzonego przez programistę.
Przykład 2: zmiana rozdzielczości przeciążenia (przed)
// 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 }); }
Przykład 2: zmiana rozdzielczości przeciążenia (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 }); }
Przywracanie ostrzeżeń instrukcji switch
Poprzednia wersja kompilatora usunęła niektóre ostrzeżenia związane z
switch
instrukcjami. Te ostrzeżenia zostały przywrócone. Kompilator wystawia teraz przywrócone ostrzeżenia, a ostrzeżenia związane z określonymi przypadkami (w tym przypadek domyślny) są teraz wydawane w wierszu zawierającym przypadek naruszenia, a nie w ostatnim wierszu instrukcji switch. W wyniku teraz wydawania tych ostrzeżeń w różnych wierszach niż w przeszłości ostrzeżenia wcześniej pomijane przy użyciu#pragma warning(disable:####)
mogą nie być już pomijane zgodnie z oczekiwaniami. Aby pominąć te ostrzeżenia zgodnie z oczekiwaniami, może być konieczne przeniesienie#pragma warning(disable:####)
dyrektywy do wiersza powyżej pierwszej sprawy przestępczej. Poniżej przedstawiono przywrócone ostrzeżenia: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
Przykład C4063 (przed)
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; } };
Przykład C4063 (po)
class settings { ... }; // as above int main() { // since C++11, use std::underlying_type to determine the underlying type of an enum typedef std::underlying_type< settings::flags> ::type flags_t; auto val = settings::bit1; switch (static_cast< flags_t> (val)) { case settings::bit0: break; case settings::bit1: break; case settings::bit0 | settings::bit1: // ok break; } };
Przykłady innych przywróconych ostrzeżeń znajdują się w dokumentacji.
#include: używanie specyfikatora katalogu nadrzędnego ".". w nazwa_ścieżki (dotyczy
/Wall
/WX
tylko )Poprzednie wersje kompilatora nie wykryły użycia specyfikatora katalogu nadrzędnego ".". w ścieżce
#include
dyrektyw. Kod napisany w ten sposób jest zwykle przeznaczony do uwzględnienia nagłówków, które istnieją poza projektem, niepoprawnie używając ścieżek względnych projektu. To stare zachowanie spowodowało ryzyko kompilowania programu przez dołączenie innego pliku źródłowego niż zamierzony przez programistę lub że te ścieżki względne nie będą przenośne do innych środowisk kompilacji. Kompilator wykrywa teraz i powiadamia programistę o kodzie napisanym w ten sposób i wyświetla opcjonalne ostrzeżenie kompilatora C4464, jeśli jest włączone.warning C4464: relative include path contains '..'
Przykład (przed)
#include "..\headers\C4426.h" // emits warning C4464
Przykład (po)
#include "C4426.h" // add absolute path to 'headers\' to your project's include directories
Ponadto, mimo że kompilator nie daje określonej diagnostyki, zalecamy również, aby specyfikator katalogu nadrzędnego ".". Nie powinien być używany do określania katalogów dołączania projektu.
#pragma optimize() rozszerza poprzedni koniec pliku nagłówka (ma to wpływ tylko na
/Wall
/WX
)Poprzednie wersje kompilatora nie wykryły zmian ustawień flag optymalizacji, które unikną pliku nagłówka zawartego w jednostce tłumaczenia. Kompilator wykrywa teraz i powiadamia programistę o kodzie napisanym w ten sposób i wyświetla opcjonalne ostrzeżenie kompilatora C4426 w lokalizacji obiektu,
#include
jeśli jest włączone. To ostrzeżenie jest wyświetlane tylko wtedy, gdy zmiany powodują konflikt z flagami optymalizacji ustawionymi przez argumenty wiersza polecenia kompilatora.warning C4426: optimization flags changed after including header, may be due to #pragma optimize()
Przykład (przed)
// C4426.h #pragma optimize("g", off) ... // C4426.h ends // C4426.cpp #include "C4426.h" // warning C4426
Przykład (po)
// C4426.h #pragma optimize("g", off) ... #pragma optimize("", on) // restores optimization flags set via command-line arguments // C4426.h ends // C4426.cpp #include "C4426.h"
Niezgodność #pragma warning(push) i ostrzeżenie #pragma (pop) (dotyczy
/Wall
/WX
tylko )Poprzednie wersje kompilatora nie wykryły
#pragma warning(push)
zmian stanu sparowanych ze#pragma warning(pop)
zmianami stanu w innym pliku źródłowym, który jest rzadko zamierzony. To stare zachowanie spowodowało ryzyko, że program zostanie skompilowany z innym zestawem ostrzeżeń włączonych niż zamierzony przez programistę, co może spowodować dyskretne złe zachowanie środowiska uruchomieniowego. Kompilator wykrywa teraz i powiadamia programistę o kodzie napisanym w ten sposób i wyświetla opcjonalne ostrzeżenie kompilatora C5031 w lokalizacji pasującego#pragma warning(pop)
elementu , jeśli jest włączone. To ostrzeżenie zawiera notatkę odwołującą się do lokalizacji odpowiadającego #pragma warning(push).warning C5031: #pragma warning(pop): likely mismatch, popping warning state pushed in different file
Przykład (przed)
// 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 ...
Przykład (po)
// C5031_part1.h #pragma warning(push) #pragma warning(disable:####) ... #pragma warning(pop) // pops the warning state pushed in this source file // C5031_part1.h ends without #pragma warning(pop) // C5031_part2.h #pragma warning(push) // pushes the warning state pushed in this source file #pragma warning(disable:####) ... #pragma warning(pop) // C5031_part1.h ends // C5031.cpp #include "C5031_part1.h" // #pragma warning state changes are self-contained and independent of other source files or their #include order. ... #include "C5031_part2.h" ...
Choć nietypowe, kod napisany w ten sposób jest czasami zamierzony. Kod napisany w ten sposób jest wrażliwy na zmiany w
#include
kolejności. Jeśli to możliwe, zalecamy, aby pliki kodu źródłowego zarządzały stanem ostrzeżenia w sposób samodzielny.Niedopasowane #pragma warning(push) (dotyczy
/Wall
/WX
tylko )Poprzednie wersje kompilatora nie wykryły niezgodnych
#pragma warning(push)
zmian stanu na końcu jednostki tłumaczenia. Kompilator wykrywa teraz i powiadamia programistę o kodzie napisanym w ten sposób i wyświetla opcjonalne ostrzeżenie kompilatora C5032 w lokalizacji niedopasowanego#pragma warning(push)
elementu , jeśli jest włączone. To ostrzeżenie jest wyświetlane tylko wtedy, gdy w jednostce tłumaczenia nie występują błędy kompilacji.warning C5032: detected #pragma warning(push) with no corresponding #pragma warning(pop)
Przykład (przed)
// 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
Przykład (po)
// C5032.h #pragma warning(push) #pragma warning(disable:####) ... #pragma warning(pop) // matches #pragma warning (push) on line 1 // C5032.h ends // C5032.cpp #include "C5032.h" ... // C5032.cpp ends -- the translation unit is completed without unmatched #pragma warning(push)
Dodatkowe ostrzeżenia mogą być wyświetlane w wyniku ulepszonego śledzenia stanu ostrzeżenia #pragma
Poprzednie wersje kompilatora śledzone #pragma zmiany stanu ostrzeżenia są wystarczająco dobre, aby wyświetlić wszystkie zamierzone ostrzeżenia. To zachowanie spowodowało ryzyko efektywnego pomijania niektórych ostrzeżeń w sytuacjach innych niż zamierzony przez programistę. Kompilator śledzi
#pragma warning
teraz stan bardziej niezawodnie — szczególnie związane ze#pragma warning
zmianami stanu wewnątrz szablonów — i opcjonalnie zgłasza nowe ostrzeżenia C5031 i C5032, które mają pomóc programisty zlokalizować niezamierzone zastosowania#pragma warning(push)
elementów i#pragma warning(pop)
.W wyniku ulepszonego
#pragma warning
śledzenia zmian stanu ostrzeżenia wcześniej nieprawidłowo pominięte lub ostrzeżenia związane z problemami, które były wcześniej błędnie diagnozowane, mogą być teraz wydawane.Ulepszona identyfikacja kodu, który nie jest osiągalny
Zmiana standardowej biblioteki języka C++ i ulepszona możliwość wbudowanych wywołań funkcji w porównaniu z poprzednimi wersjami kompilatora może pozwolić kompilatorowi udowodnić, że określony kod jest teraz nieosiągalny. To nowe zachowanie może spowodować powstanie nowych i częściej wystawianych wystąpień ostrzeżenia C4720.
warning C4720: unreachable code
W wielu przypadkach to ostrzeżenie może być wystawiane tylko podczas kompilowania z włączonymi optymalizacjami, ponieważ optymalizacje mogą wstawić więcej wywołań funkcji, wyeliminować nadmiarowy kod lub w inny sposób umożliwić ustalenie, że określony kod jest niemożliwy do osiągnięcia. Zaobserwowaliśmy, że w blokach try/catch często wystąpiły nowe wystąpienia ostrzeżenia C4720, szczególnie w odniesieniu do używania elementu std::find.
Przykład (przed)
try { auto iter = std::find(v.begin(), v.end(), 5); } catch (...) { do_something(); // ok }
Przykład (po)
try { auto iter = std::find(v.begin(), v.end(), 5); } catch (...) { do_something(); // warning C4702: unreachable code }
Ulepszenia zgodności w aktualizacji Update 2
Dodatkowe ostrzeżenia i błędy mogą być wystawiane w wyniku częściowej obsługi wyrażenia SFINAE
Poprzednie wersje kompilatora nie analizuje niektórych rodzajów wyrażeń wewnątrz
decltype
specyfikatorów z powodu braku obsługi wyrażenia SFINAE. To stare zachowanie było nieprawidłowe i nie jest zgodne ze standardem C++. Kompilator analizuje teraz te wyrażenia i ma częściową obsługę wyrażenia SFINAE ze względu na ciągłe ulepszenia zgodności. W rezultacie kompilator wydaje teraz ostrzeżenia i błędy znalezione w wyrażeniach, które poprzednie wersje kompilatora nie zostały przeanalizowane.Gdy to nowe zachowanie analizuje
decltype
wyrażenie zawierające typ, który nie został jeszcze zadeklarowany, kompilator wystawia błąd kompilatora C2039 w wyniku.error C2039: 'type': is not a member of 'global namespace'
Przykład 1: użycie typu niezadeklarowanego (przed)
struct s1 { template < typename T> auto f() - > decltype(s2< T> ::type::f()); // error C2039 template< typename> struct s2 {}; }
Przykład 1 (po)
struct s1 { template < typename> // forward declare s2struct s2; template < typename T> auto f() - > decltype(s2< T> ::type::f()); template< typename> struct s2 {}; }
Gdy to nowe zachowanie analizuje
decltype
wyrażenie, które nie ma niezbędnego użycia słowa kluczowegotypename
, aby określić, że nazwa zależna jest typem, kompilator wystawia ostrzeżenie kompilatora C4346 wraz z błędem kompilatora 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'
Przykład 2: nazwa zależna nie jest typem (przed)
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 };
Przykład 2 (po)
template < typename T> struct s1 { ... }; // as above template < typename T> struct s2 { ... }; // as above template < typename T> T declval(); struct s { template < typename T> auto f(T t) - > decltype(t(declval< S1< typename S2< T> ::type> ::type> ())); };
volatile
Zmienne składowe uniemożliwiają niejawnie zdefiniowane konstruktory i operatory przypisaniaPoprzednie wersje kompilatora zezwalały na klasę, która ma
volatile
zmienne składowe, aby mieć domyślne konstruktory kopiowania/przenoszenia i automatycznie generowane operatory przypisania kopiowania/przenoszenia. To stare zachowanie było nieprawidłowe i nie jest zgodne ze standardem C++. Kompilator uwzględnia teraz klasę zawierającą zmienne składowe, które mająvolatile
nietrywialne operatory konstrukcji i przypisania, co uniemożliwia automatyczne generowanie domyślnych implementacji tych operatorów. Gdy taka klasa jest członkiem unii (lub anonimowej unii wewnątrz klasy), konstruktory kopiowania/przenoszenia i operatory przypisania kopiowania/przenoszenia unii (lub klasy zawierającej anonimową unię) będą niejawnie zdefiniowane jako usunięte. Próba skonstruowania lub skopiowania unii (lub klasy zawierającej anonimową unię) bez jawnego zdefiniowania ich jest błędem, a w rezultacie błąd kompilatora problemów kompilatora C2280.error C2280: 'B::B(const B &)': attempting to reference a deleted function
Przykład (przed)
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
Przykład (po)
struct A { int i; int j; }; extern volatile A* pa; A getA() // returns an A instance copied from contents of pa { A a; a.i = pa - > i; a.j = pa - > j; return a; } struct B; // as above B b1{ GetA() }; B b2(b1); // error C2280
Statyczne funkcje składowe nie obsługują kwalifikatorów cv.
Poprzednie wersje programu Visual Studio 2015 zezwalały na statyczne funkcje składowe z kwalifikatorami cv. To zachowanie jest spowodowane regresją w programach Visual Studio 2015 i Visual Studio 2015 Update 1; Program Visual Studio 2013 i poprzednie wersje kompilatora odrzucają kod napisany w ten sposób. Zachowanie programów Visual Studio 2015 i Visual Studio 2015 Update 1 jest nieprawidłowe i nie jest zgodne ze standardem C++. Program Visual Studio 2015 Update 2 odrzuca kod napisany w ten sposób i zamiast tego zgłasza błąd kompilatora C2511.
error C2511: 'void A::func(void) const': overloaded member function not found in 'A'
Przykład (przed)
struct A { static void func(); }; void A::func() const {} // C2511
Example(after)
struct A { static void func(); }; void A::func() {} // removed const
Przekazywanie deklaracji wyliczenia nie jest dozwolone w kodzie WinRT (dotyczy
/ZW
tylko )Kod skompilowany dla środowisko wykonawcze systemu Windows (WinRT) nie zezwala na
enum
deklarowanie typów, podobnie jak w przypadku kompilowania zarządzanego kodu C++ dla programu .Net Framework przy użyciu przełącznika kompilatora/clr
. To zachowanie gwarantuje, że rozmiar wyliczenia jest zawsze znany i może być poprawnie przewidywany dla systemu typów WinRT. Kompilator odrzuca kod napisany w ten sposób i wystawia błąd kompilatora C2599 wraz z błędem kompilatora C3197.error C2599: 'CustomEnum': the forward declaration of a WinRT enum is not allowed
error C3197: 'public': can only be used in definitions
Przykład (przed)
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; } };
Przykład (po)
// forward declaration of CustomEnum removed namespace A { public enum class CustomEnum : int32 { Value1 }; } public ref class Component sealed { public: CustomEnum f() { return CustomEnum::Value1; } };
Przeciążony operator nienależące do elementu członkowskiego — nowy, a usuwanie operatora nie może być zadeklarowane w tekście (poziom 1 (
/W1
) domyślnie)Poprzednie wersje kompilatora nie wydają ostrzeżenia, gdy funkcje usuwania operatora innego niż składowe są deklarowane w tekście. Kod napisany w ten sposób jest źle sformułowany (bez wymaganej diagnostyki) i może powodować problemy z pamięcią wynikające z niezgodności nowych i usuniętych operatorów (szczególnie w przypadku użycia razem z przydziałem wielkości), które mogą być trudne do zdiagnozowania. Kompilator wydaje teraz ostrzeżenie kompilatora C4595, aby ułatwić identyfikację kodu napisanego w ten sposób.
warning C4595: 'operator new': non-member operator new or delete functions may not be declared inline
Przykład (przed)
inline void* operator new(size_t sz) // warning C4595 { ... }
Przykład (po)
void* operator new(size_t sz) // removed inline { ... }
Naprawienie kodu napisanego w ten sposób może wymagać przeniesienia definicji operatorów z pliku nagłówka i do odpowiedniego pliku źródłowego.
Ulepszenia zgodności w aktualizacji Update 3
std::is_convertable wykrywa teraz samodzielne przypisywanie (biblioteka standardowa)
Poprzednie wersje
std::is_convertable
cech typu nie wykryły poprawnie samodzielnego przypisania typu klasy, gdy jego konstruktor kopiujący jest usuwany lub prywatny.std::is_convertable<>::value
Teraz jest poprawnie ustawiana nafalse
wartość , gdy jest stosowana do typu klasy z usuniętym lub prywatnym konstruktorem kopiowania.Brak diagnostyki kompilatora skojarzonej z tą zmianą.
Przykład
#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");
W poprzednich wersjach kompilatora statyczne asercji w dolnej części tego przykładu zostały przekazane, ponieważ
std::is_convertable<>::value
zostały niepoprawnie ustawione natrue
.std::is_convertable<>::value
Teraz jest poprawnie ustawiona nafalse
wartość , co powoduje niepowodzenie asercji statycznych.Domyślne lub usunięte trywialne kopiowanie i przenoszenie konstruktorów przestrzega specyfikatorów dostępu
Poprzednie wersje kompilatora nie sprawdzały specyfikatora dostępu domyślnego lub usuniętego trywialnego kopiowania i przenoszenia konstruktorów przed zezwoleniem na ich wywoływanie. To stare zachowanie było nieprawidłowe i nie jest zgodne ze standardem C++. W niektórych przypadkach to stare zachowanie spowodowało ryzyko dyskretnego generowania nieprawidłowego kodu, co spowodowało nieprzewidywalne zachowanie środowiska uruchomieniowego. Kompilator sprawdza teraz specyfikator dostępu domyślnego lub usuniętego trywialnego kopiowania i przenoszenia konstruktorów, aby określić, czy można go wywołać, a jeśli nie, wystawia ostrzeżenie kompilatora C2248 w wyniku.
error C2248: 'S::S' cannot access private member declared in class 'S'
Przykład (przed)
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 }
Przykład (po)
class S { public: S() = default; private: S(const S&) = default; }; void f(const S&); // pass S by reference int main() { S s; f(s); }
Wycofanie obsługi przypisanych kodów ATL (poziom 1 (
/W1
) domyślnie)Poprzednie wersje kompilatora obsługiwały przypisany kod ATL. W następnej fazie usuwania obsługi przypisanego kodu ATL, który rozpoczął się w programie Visual Studio 2008, przypisany kod ATL został przestarzały. Kompilator wydaje teraz ostrzeżenie kompilatora C4467, aby ułatwić zidentyfikowanie tego rodzaju przestarzałego kodu.
warning C4467: Usage of ATL attributes is deprecated
Jeśli chcesz nadal używać przypisanego kodu ATL, dopóki obsługa nie zostanie usunięta z kompilatora, możesz wyłączyć to ostrzeżenie, przekazując
/Wv:18
argumenty wiersza polecenia lub/wd:4467
do kompilatora lub dodając#pragma warning(disable:4467)
kod źródłowy.Przykład 1 (przed)
[uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")] class A {};
Przykład 1 (po)
__declspec(uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")) A {};
Czasami może być konieczne utworzenie lub utworzenie pliku IDL w celu uniknięcia użycia przestarzałych atrybutów ATL, jak w przykładowym kodzie poniżej
Przykład 2 (przed)
[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 { // ... };
Najpierw utwórz plik *.idl; Wygenerowany plik vc140.idl może służyć do uzyskania pliku *.idl zawierającego interfejsy i adnotacje.
Następnie dodaj krok MIDL do kompilacji, aby upewnić się, że są generowane definicje interfejsu języka C++.
Przykład 2 IDL (po)
import "docobj.idl"; [ object, local, uuid(9e66a290 - 4365 - 11d2 - a997 - 00c04fa37ddb) ] interface ICustom : IUnknown { HRESULT Custom([in] long l, [out, retval] long *pLong); [local] HRESULT CustomLocal([in] long l, [out, retval] long *pLong); }; [version(1.0), uuid(29079a2c - 5f3f - 3325 - 99a1 - 3ec9c40988bb)] library Foo { importlib("stdole2.tlb"); importlib("olepro32.dll"); [ version(1.0), appobject,uuid(9e66a294 - 4365 - 11d2 - a997 - 00c04fa37ddb) ] coclass CFoo { interface ICustom; }; }
Następnie użyj atl bezpośrednio w pliku implementacji, jak w poniższym przykładowym kodzie.
Przykład 2 Implementacja (po)
#include <idl.header.h> #include <atlbase.h> class ATL_NO_VTABLE CFooImpl : public ICustom, public ATL::CComObjectRootEx< CComMultiThreadModel> { public: BEGIN_COM_MAP(CFooImpl) COM_INTERFACE_ENTRY(ICustom) END_COM_MAP() };
Wstępnie skompilowane pliki nagłówka (PCH) i niedopasowane dyrektywy #include (mają wpływ tylko na
/Wall
/WX
)Poprzednie wersje kompilatora zaakceptowały
#include
niezgodność dyrektyw w plikach źródłowych między kompilacjami-Yc
i-Yu
podczas używania plików prekompilowanego nagłówka (PCH). Kod napisany w ten sposób nie jest już akceptowany przez kompilator. Kompilator wydaje teraz ostrzeżenie kompilatora CC4598, aby ułatwić identyfikowanie niezgodnych#include
dyrektyw podczas korzystania z plików PCH.warning C4598: 'b.h': included header file specified for Ycc.h at position 2 does not match Yuc.h at that position
Przykład (przed):
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"
Przykład (po)
X.cpp (-Ycc.h)
#include "a.h" #include "b.h" #include "c.h"
Z.cpp (-Yuc.h)
#include "a.h" #include "b.h" // matched order relative to X.cpp #include "c.h"
Wstępnie skompilowane pliki nagłówka (PCH) i niedopasowane katalogi dołączania (dotyczy
/Wall
/WX
tylko )Poprzednie wersje kompilatora zaakceptowały niezgodność argumentów wiersza polecenia dołączania () katalogu (
-I
) do kompilatora między kompilacjami-Yc
i-Yu
podczas używania plików prekompilowanego nagłówka (PCH). Kod napisany w ten sposób nie jest już akceptowany przez kompilator. Kompilator wydaje teraz ostrzeżenie kompilatora CC4599, aby ułatwić identyfikację niezgodnych argumentów wiersza polecenia dołączania katalogu (-I
) podczas korzystania z plików PCH.warning C4599: '-I..' : specified for Ycc.h at position 1 does not match Yuc.h at that position
Przykład (przed)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h Z.cpp
Przykład (po)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h -I.. Z.cpp
Zmiany zgodności programu Visual Studio 2013
Compiler
Ostatnie słowo kluczowe generuje teraz nierozwiązany błąd symbolu, w którym zostałby skompilowany wcześniej:
struct S1 { virtual void f() = 0; }; struct S2 final : public S1 { virtual void f(); }; int main(S2 *p) { p->f(); }
We wcześniejszych wersjach błąd nie został wystawiony, ponieważ wywołanie było wywołaniem
virtual
, mimo to program ulegał awarii w czasie wykonywania. Teraz zostaje zgłoszony błąd konsolidatora, ponieważ wiadomo, że klasa jest ostateczna. W tym przykładzie, aby naprawić błąd, należy połączyć się z obj zawierającym definicjęS2::f
.W przypadku korzystania z funkcji zaprzyjaźnionych w przestrzeniach nazw należy ponownie zadeklarować funkcję znajomą przed jej odwołaniem lub zostanie wyświetlony błąd, ponieważ kompilator jest teraz zgodny ze standardem ISO C++. Na przykład ten przykład nie jest już kompilowany:
namespace NS { class C { void func(int); friend void func(C* const) {} }; void C::func(int) { NS::func(this); // error } }
Aby poprawić ten kod, zadeklaruj
friend
funkcję: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); }
Język C++ Standard nie zezwala na jawną specjalizację w klasie. Mimo że kompilator języka Microsoft C++ pozwala na to w niektórych przypadkach, w takich przypadkach, w takich jak poniższy przykład, zostanie wygenerowany błąd, ponieważ kompilator nie uwzględnia drugiej funkcji jako specjalizacji pierwszego.
template < int N> class S { public: template void f(T& val); template < > void f(char val); }; template class S< 1>;
Aby poprawić ten kod, zmodyfikuj drugą funkcję:
template <> void f(char& val);
Kompilator nie próbuje już uściślać dwóch funkcji w poniższym przykładzie, a teraz emituje błąd:
template< typename T> void Func(T* t = nullptr); template< typename T> void Func(...); int main() { Func< int>(); // error }
Aby poprawić ten kod, wyjaśnij wywołanie:
template< typename T> void Func(T* t = nullptr); template< typename T> void Func(...); int main() { Func< int>(nullptr); // ok }
Zanim kompilator jest zgodny z normą ISO C++11, skompilowałby następujący kod i spowodował
x
rozwiązanie problemu z typemint
:auto x = {0}; int y = x;
Ten kod jest teraz rozpoznawany
x
jako typstd::initializer_list<int>
i powoduje błąd w następnym wierszu, który próbuje przypisaćx
do typuint
. (Domyślnie nie ma konwersji). Aby poprawić ten kod, użyj polecenia , aby zastąpićauto
elementint
:int x = {0}; int y = x;
Inicjowanie agregacji nie jest już dozwolone, gdy typ wartości po prawej stronie nie jest zgodny z typem inicjowanej wartości po lewej stronie, a błąd jest wyświetlany, ponieważ standard ISO C++11 wymaga jednolitej inicjalizacji do pracy bez zawężenia konwersji. Wcześniej, jeśli dostępna była konwersja zawężania, ostrzeżenie kompilatora (poziom 4) C4242 zostałoby wydane zamiast błędu.
int i = 0; char c = {i}; // error
Aby poprawić ten kod, dodaj jawną konwersję zawężającą:
int i = 0; char c = {static_cast<char>(i)};
Następujące inicjowanie nie jest już dozwolone:
void *p = {{0}};
Aby poprawić ten kod, użyj którejś z tych postaci:
void *p = 0; // or void *p = {0};
Wyszukiwanie nazw zostało zmienione. Poniższy kod jest rozpoznawany inaczej w kompilatorze języka C++ w programach Visual Studio 2012 i Visual Studio 2013:
enum class E1 { a }; enum class E2 { b }; int main() { typedef E2 E1; E1::b; }
W programie Visual Studio 2012
E1
wyrażenieE1::b
in rozpoznane jako::E1
w zakresie globalnym. W programie Visual Studio 2013E1
wyrażenieE1::b
jest rozpoznawane jakotypedef E2
definicja wmain()
pliku i ma typ::E2
.Układ obiektu został zmieniony. W x64, układ obiektu klasy może się zmienić w porównaniu z poprzednimi wydaniami. Jeśli ma
virtual
funkcję, ale nie ma klasy bazowej, która mavirtual
funkcję, model obiektów kompilatora wstawia wskaźnik dovirtual
tabeli funkcji po układzie składowym danych. Oznacza to, że układ może nie być optymalny we wszystkich przypadkach. W poprzednich wersjach optymalizacja dla x64 próbowała ulepszyć układ, ale ponieważ nie działa prawidłowo w złożonych sytuacjach kodu, została usunięta w programie Visual Studio 2013. Na przykład, rozważmy ten kod:__declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };
W programie Visual Studio 2013 wynik
sizeof(S2)
w wersji x64 wynosi 48, ale w poprzednich wersjach daje 32. Aby wykonać tę ocenę do 32 w kompilatorze języka C++ programu Visual Studio 2013 dla x64, dodaj fikcyjną klasę bazowąvirtual
, która ma funkcję:__declspec(align(16)) struct S1 { }; struct dummy { virtual ~dummy() {} }; struct S2 : public dummy { virtual ~S2(); void *p; S1 s; };
Aby znaleźć miejsca w kodzie, które wcześniejsza wersja próbowałaby zoptymalizować, użyj kompilatora z tej wersji wraz z opcją kompilatora
/W3
i włącz ostrzeżenie C4370. Na przykład:#pragma warning(default:4370) __declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };
Przed programem Visual Studio 2013 ten kod zwraca następujący komunikat: "ostrzeżenie C4370: "S2" : układ klasy został zmieniony z poprzedniej wersji kompilatora z powodu lepszego pakowania".
Kompilator x86 ma ten sam nieoptymalny problem z układem we wszystkich wersjach kompilatora. Na przykład, jeśli ten kod jest kompilowany dla architektury x86:
struct S { virtual ~S(); int i; double d; };
Wynik
sizeof(S)
wynosi 24. Można go jednak zmniejszyć do 16, jeśli użyjesz obejścia wymienionego dla x64:struct dummy { virtual ~dummy() {} }; struct S : public dummy { virtual ~S(); int i; double d; };
Standardowa biblioteka
Kompilator języka C++ w programie Visual Studio 2013 wykrywa niezgodność w _ITERATOR_DEBUG_LEVEL, który został zaimplementowany w programie Visual Studio 2010 i niezgodności środowiska RuntimeLibrary. Te niezgodności występują, gdy opcje /MT
kompilatora (wersja statyczna), /MTd
(debugowanie statyczne), /MD
(wersja dynamiczna) i /MDd
(debugowanie dynamiczne) są mieszane.
Jeśli kod potwierdzi symulowane szablony aliasów poprzedniej wersji, musisz go zmienić. Na przykład zamiast
allocator_traits<A>::rebind_alloc<U>::other
, teraz musisz powiedziećallocator_traits<A>::rebind_alloc<U>
. Mimoratio_add<R1, R2>::type
że nie jest już konieczne i teraz zalecamy, aby powiedziećratio_add<R1, R2>
, pierwszy będzie nadal kompilowany, ponieważratio<N, D>
jest wymagany do "typu" typedef dla zmniejszonego współczynnika, który będzie tego samego typu, jeśli jest już zmniejszony.Należy użyć
#include <algorithm>
podczas wywoływania poleceniastd::min()
lubstd::max()
.Jeśli istniejący kod używa symulowanych wyliczenia w zakresie poprzedniej wersji — tradycyjnych wyliczenia niezakresowe opakowane w przestrzenie nazw — musisz go zmienić. Jeśli na przykład odwołujesz się do typu
std::future_status::future_status
, teraz musisz powiedziećstd::future_status
. Jednak większość kodu nie ma wpływu — na przykładstd::future_status::ready
nadal kompiluje się.explicit operator bool()
jest bardziej rygorystyczny niż operator nieokreślony-bool-type().explicit operator bool()
zezwala na jawne konwersje na wartość logiczną — na przykład podaneshared_ptr<X> sp
wartości , istatic_cast<bool>(sp)
bool b(sp)
są prawidłowe — oraz warunkowe "konwersje kontekstowe" na wartość logiczną — na przykładif (sp)
,!sp
,sp &&
niezależnie od tego.explicit operator bool()
Jednak zabrania niejawnych konwersji na wartość logiczną, więc nie można powiedziećbool b = sp;
i podanego typu zwracanego wartości logicznej, nie można powiedziećreturn sp
.Teraz, gdy prawdziwe szablony wariadyczne są implementowane, _VARIADIC_MAX i powiązane makra nie mają efektu. Jeśli nadal definiujesz _VARIADIC_MAX, jest on ignorowany. Jeśli przyjmiesz nasze rozwiązania makr przeznaczone do wspierania symulowanych szablonów wariadycznych w jakikolwiek inny sposób, musisz zmienić kod.
Oprócz zwykłych słów kluczowych nagłówki standardowej biblioteki języka C++ zabraniają teraz zastępowania makra słowami kluczowymi kontekstowymi i końcowymi.
reference_wrapper
,ref()
icref()
teraz zabrania powiązania z obiektami tymczasowymi.<random>
teraz ściśle wymusza warunki wstępne kompilowania.Różne cechy typu standardowej biblioteki języka C++ mają warunek wstępny "T musi być kompletnym typem". Mimo że kompilator wymusza teraz ten warunek wstępny bardziej ściśle, może nie wymuszać go we wszystkich sytuacjach. (Ponieważ naruszenia warunków wstępnych biblioteki standardowej języka C++ wyzwalają niezdefiniowane zachowanie, standard nie gwarantuje wymuszania).
Biblioteka Standardowa języka C++ nie obsługuje programu
/clr:oldSyntax
.Specyfikacja języka C++11 dla
common_type<>
nieoczekiwanych i niepożądanych konsekwencji, w szczególności zwracacommon_type<int, int>::type
wartośćint&&
. W związku z tym kompilator implementuje proponowane rozwiązanie problemu grupy roboczej biblioteki 2141, co zwracacommon_type<int, int="">::type
wartośćint
.Jako efekt uboczny tej zmiany przypadek tożsamości nie działa już (
common_type<T>
nie zawsze powoduje typT
). To zachowanie jest zgodne z proponowanym rozwiązaniem, ale powoduje uszkodzenie kodu, który polegał na poprzednim zachowaniu.Jeśli potrzebujesz cech typu tożsamości, nie używaj standardu
std::identity
zdefiniowanego w<type_traits>
programie , ponieważ nie będzie działać dla elementu<void>
. Zamiast tego wdróż własną cechę typu tożsamości odpowiednią do własnych potrzeb. Oto przykład:template < typename T> struct Identity { typedef T type; };
MFC i ATL
Tylko program Visual Studio 2013: biblioteka MFC MBCS nie jest uwzględniona w programie Visual Studio, ponieważ Standard Unicode jest tak popularny, a użycie MBCS znacznie spadło. Ta zmiana podtrzymuje również ściślejszą relację między MFC a Windows SDK. ponieważ wiele nowych kontrolek i komunikatów wymaga Unicode. Jeśli jednak musisz nadal korzystać z biblioteki MFC MBCS, możesz pobrać ją z Centrum pobierania Microsoft w bibliotece MFC Multibyte dla programu Visual Studio 2013. Pakiet redystrybucyjny Visual C++ wciąż zawiera tę bibliotekę. (Uwaga: biblioteka DLL MBCS jest zawarta w składnikach instalacyjnych języka C++ w programie Visual Studio 2015 lub nowszym).
Ułatwienia dostępu dla wstążki MFC są zmieniane. Zamiast architektury jednowarstwowej istnieje teraz architektura hierarchiczna. Nadal możesz użyć starego zachowania, wywołując polecenie
CRibbonBar::EnableSingleLevelAccessibilityMode()
.CDatabase::GetConnect
Metoda jest usuwana. Aby zwiększyć bezpieczeństwo, parametry połączenia jest teraz przechowywany w postaci zaszyfrowanej i jest odszyfrowywana tylko w razie potrzeby; nie można jej zwracać jako zwykłego tekstu. Ciąg można uzyskać przy użyciuCDatabase::Dump
metody .CWnd::OnPowerBroadcast
Podpis jest zmieniany. Sygnatura tego programu obsługi komunikatu została zmieniona, aby przyjąć LPARAM jako drugi parametr.Podpisy są zmieniane tak, aby obsługiwały programy obsługi komunikatów. Listy parametrów dla poniższych funkcji zostały zmienione, aby używać nowo dodanych programów obsługi komunikatów ON_WM_*:
CWnd::OnDisplayChange
zmieniono na (UINT, int, int) zamiast (WPARAM, LPARAM), aby nowe makro ON_WM_DISPLAYCHANGE można było używać na mapie komunikatów.CFrameWnd::OnDDEInitiate
zmieniono wartość na (CWnd*, UINT, UNIT) zamiast (WPARAM, LPARAM), aby nowe makro ON_WM_DDE_INITIATE można było używać na mapie komunikatów.CFrameWnd::OnDDEExecute
zmieniono wartość na (CWnd*, HANDLE) zamiast (WPARAM, LPARAM), aby nowe makro ON_WM_DDE_EXECUTE można było używać na mapie komunikatów.CFrameWnd::OnDDETerminate
zmieniono wartość na (CWnd*) jako parametr zamiast (WPARAM, LPARAM), aby nowe makro ON_WM_DDE_TERMINATE można było użyć na mapie komunikatów.CMFCMaskedEdit::OnCut
zmieniono wartość na brak parametrów zamiast (WPARAM, LPARAM), aby nowe makro ON_WM_CUT można było używać na mapie komunikatów.CMFCMaskedEdit::OnClear
zmieniono wartość na brak parametrów zamiast (WPARAM, LPARAM), aby nowe makro ON_WM_CLEAR można było używać na mapie komunikatów.CMFCMaskedEdit::OnPaste
zmieniono wartość na brak parametrów zamiast (WPARAM, LPARAM), aby nowe makro ON_WM_PASTE można było używać na mapie komunikatów.
#ifdef
dyrektywy w plikach nagłówków MFC są usuwane. Usunięto wiele#ifdef
dyrektyw w plikach nagłówków MFC powiązanych z nieobsługiwaną wersją systemu Windows (WINVER < 0x0501
).Biblioteka DLL ATL (atl120.dll) jest usuwana. ATL jest obecnie dostarczany jako nagłówki i biblioteka statyczna (atls.lib).
Usunięto bibliotekę Atlsd.lib, atlsn.lib i atlsnd.lib. Atls.lib nie ma już zależności zestawu znaków ani kodu, który jest specyficzny dla wersji do debugowania/oficjalnych. Ponieważ działa tak samo dla Unicode/ANSI i wersji do debugowania/oficjalnych, wymagana jest tylko jedna wersja biblioteki.
Narzędzie śledzenia ATL/MFC jest usuwane wraz z biblioteką DLL ATL, a mechanizm śledzenia jest uproszczony. Konstruktor
CTraceCategory
przyjmuje teraz jeden parametr (nazwę kategorii), a makra TRACE nazywają funkcje raportowania debugowania CRT.
Zmiany powodujące niezgodność programu Visual Studio 2012
Compiler
Opcja kompilatora została zmieniona
/Yl
. Domyślnie kompilator używa tej opcji, co może prowadzić do LNK2011 błędów w określonych warunkach. Aby uzyskać więcej informacji, zobacz /Yl (Wstrzykiwanie odwołania PCH do biblioteki debugowania).W kodzie skompilowanym przy użyciu metody
/clr
enum
słowo kluczowe klasy definiuje wyliczenie języka C++11, a nie wyliczenie środowiska uruchomieniowego języka wspólnego (CLR). Aby zdefiniować wyliczenie CLR, należy jawnie określić jego dostępność.Użyj słowa kluczowego szablonu, aby jawnie uściślić nazwę zależną (zgodność ze standardem języka C++). W poniższym przykładzie wyróżnione słowo kluczowe szablonu jest obowiązkowe, aby rozwiązać niejednoznaczność. Aby uzyskać więcej informacji, zobacz Rozpoznawanie nazw dla typów zależnych.
template < typename X = "", typename = "" AY = ""> struct Container { typedef typename AY::template Rebind< X> ::Other AX; };
Stałe wyrażenie typu float nie jest już dozwolone jako argument szablonu, jak pokazano w poniższym przykładzie.
template<float n=3.14> struct B {}; // error C2993: 'float': illegal type for non-type template parameter 'n'
Kod, który jest kompilowany przy użyciu
/GS
opcji wiersza polecenia i który ma lukę w zabezpieczeniach poza jednym może prowadzić do zakończenia procesu w czasie wykonywania, jak pokazano w poniższym przykładzie pseudokodu.char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminate
Domyślna architektura kompilacji x86 została zmieniona na SSE2; dlatego kompilator może emitować instrukcje SSE i będzie używać rejestrów XMM do wykonywania obliczeń zmiennoprzecinkowych. Jeśli chcesz przywrócić poprzednie zachowanie, użyj
/arch:IA32
flagi kompilatora, aby określić architekturę jako IA32.Kompilator może wystawiać ostrzeżenia kompilatora Ostrzeżenie (poziom 4) C4703 i C4701, gdzie wcześniej tego nie zrobił. Kompilator stosuje silniejsze kontrole użycia niezainicjowanych zmiennych lokalnych typu wskaźnika.
Po określeniu nowej flagi
/HIGHENTROPYVA
konsolidatora system Windows 8 zwykle powoduje, że alokacje pamięci zwracają adres 64-bitowy. (Przed systemem Windows 8 takie alokacje częściej zwracały adresy, które były mniejsze niż 2 GB). Ta zmiana może spowodować uwidocznienie usterek obcięcia wskaźnika w istniejącym kodzie. Domyślnie ten przełącznik jest włączony. Aby wyłączyć to zachowanie, określ wartość/HIGHENTROPYVA:NO
.Zarządzany kompilator (Visual Basic/C#) obsługuje
/HIGHENTROPYVA
również kompilacje zarządzane. Jednak w tym przypadku właściwość/HIGHENTROPYVAswitch
jest domyślnie wyłączona.
IDE
- Chociaż zalecamy, aby nie tworzyć aplikacji Windows Forms w języku C++/CLI, obsługiwana jest konserwacja istniejących aplikacji interfejsu użytkownika języka C++/CLI. Jeśli musisz utworzyć aplikację Windows Forms lub inną aplikację interfejsu użytkownika platformy .NET, użyj języka C# lub Visual Basic. Używaj języka C++/interfejsu wiersza polecenia tylko do celów współdziałania.
Biblioteka wzorców równoległych i biblioteka środowiska uruchomieniowego współbieżności
Wyliczenie SchedulerType
elementu UmsThreadDefault
jest przestarzałe. UmsThreadDefault
Specyfikacja generuje przestarzałe ostrzeżenie i wewnętrznie mapuje z powrotem na ThreadScheduler
.
Standardowa biblioteka
Po zmianie powodującej niezgodność między standardami C++98/03 i C++11 używanie jawnych argumentów szablonu do wywoływania
make_pair()
— tak jak wmake_pair<int, int>(x, y)
przypadku — zwykle nie kompiluje się w programie Visual C++ w programie Visual Studio 2012. Rozwiązaniem jest zawsze wywoływaniemake_pair()
bez jawnych argumentów szablonu — tak jak w plikumake_pair(x, y)
. Podanie jawnych argumentów szablonu pokonuje przeznaczenie funkcji. Jeśli potrzebujesz dokładnej kontroli nad typem wynikowym, użyj poleceniapair
zamiastmake_pair
— jak w plikupair<short, short>(int1, int2)
.Kolejna zmiana powodująca niezgodność między standardami C++98/03 i C++11: Gdy A jest niejawnie konwertowana na B i B, jest niejawnie konwertowana na język C, ale A nie jest niejawnie konwertowana na C, C++98/03 i Visual Studio 2010, które mogą być konwertowane
pair<A, X>
(niejawnie lub jawnie) napair<C, X>
. (Inny typ, X, nie jest tutaj interesujący i nie jest specyficzny dla pierwszego typu w parze). Kompilator języka C++ w programie Visual Studio 2012 wykrywa, że element A nie jest niejawnie konwertowany na język C i usuwa konwersję pary z rozpoznawania przeciążeń. Ta zmiana jest pozytywna dla wielu scenariuszy. Na przykład przeciążenie ifunc(const pair<string, string>&)
wywołaniepair<const char *, const char *>
func(const pair<int, int>&)
func()
polecenia za pomocą polecenia skompiluje się z tą zmianą. Jednak ta zmiana powoduje przerwanie kodu, który polegał na agresywnych konwersjach par. Taki kod można zwykle naprawić, wykonując jedną część konwersji jawnie — na przykład przekazującmake_pair(static_cast<B>(a), x)
do funkcji, która oczekujepair<C, X>
.Symulowane szablony variadzkie programu Visual Studio 2010 — na przykład
make_shared<T>(arg1, arg2, argN)
— do limitu 10 argumentów przez wykorzeczenie przeciążeń i specjalizacji z maszynami preprocesorowymi. W programie Visual Studio 2012 ten limit jest ograniczony do pięciu argumentów, aby skrócić czas kompilacji i zużycie pamięci kompilatora dla większości użytkowników. Można jednak ustawić poprzedni limit, jawnie definiując _VARIADIC_MAX jako 10 dla całego projektu.C++11 17.6.4.3.1 [macro.names]/2 zabrania zamiany makra słów kluczowych, gdy dołączane są nagłówki standardowej biblioteki języka C++. Nagłówki emitują teraz błędy kompilatora, jeśli wykrywają słowa kluczowe zastąpione makrami. (Definiowanie _ALLOW_KEYWORD_MACROS umożliwia kompilowanie takiego kodu, ale zdecydowanie odradzamy to użycie). Wyjątkiem jest to, że forma
new
makra jest domyślnie dozwolona, ponieważ nagłówki są kompleksowo bronione za pomocą polecenia/#pragma push_macro("new")
#undef new
/#pragma pop_macro("new")
. Definiowanie _ENFORCE_BAN_OF_MACRO_NEW dokładnie określa jego nazwę.Aby zaimplementować różne optymalizacje i testy debugowania, implementacja standardowej biblioteki C++ celowo przerywa zgodność binarną między wersjami programu Visual Studio (2005, 2008, 2010, 2012). Gdy używana jest standardowa biblioteka języka C++, zabrania mieszania plików obiektów i bibliotek statycznych kompilowanych przy użyciu różnych wersji w jednym pliku binarnym (EXE lub DLL) i zabrania przekazywania obiektów biblioteki standardowej języka C++ między plikami binarnymi kompilowanymi przy użyciu różnych wersji. Mieszanie plików obiektów i bibliotek statycznych (przy użyciu standardowej biblioteki języka C++ skompilowanej przy użyciu programu Visual Studio 2010 z plikami skompilowanymi przy użyciu kompilatora C++ w programie Visual Studio 2012 emituje błędy konsolidatora dotyczące niezgodności _MSC_VER, gdzie _MSC_VER jest makro zawierające wersję główną kompilatora (1700 dla języka Visual C++ w programie Visual Studio 2012). To sprawdzenie nie może wykryć mieszania bibliotek DLL i nie może wykryć mieszania, które obejmuje program Visual Studio 2008 lub starszy.
Oprócz wykrywania niezgodności _ITERATOR_DEBUG_LEVEL, które zostały zaimplementowane w programie Visual Studio 2010, kompilator języka C++ w programie Visual Studio 2012 wykrywa niezgodność bibliotek środowiska uruchomieniowego. Te niezgodności występują, gdy opcje
/MT
kompilatora (wersja statyczna),/MTd
(debugowanie statyczne),/MD
(wersja dynamiczna) i/MDd
(debugowanie dynamiczne) są mieszane.operator<()
, ,operator>()
operator<=()
ioperator>=()
były wcześniej dostępne dlastd::unordered_map
rodzin kontenerów istdext::hash_map
, chociaż ich implementacje nie były przydatne. Te nietypowe operatory zostały usunięte w programie Visual C++ w programie Visual Studio 2012. Ponadto wdrożenieoperator==()
ioperator!=()
dlastd::unordered_map
rodziny zostało rozszerzone o pokryciestdext::hash_map
rodziny. (Zalecamy unikanie używaniastdext::hash_map
rodziny w nowym kodzie).C++11 22.4.1.4 [locale.codecvt] określa, że
codecvt::length()
icodecvt::do_length()
powinien przyjmować modyfikowalnestateT&
parametry, ale program Visual Studio 2010 wziął wartośćconst stateT&
. Kompilator języka C++ w programie Visual Studio 2012 jeststateT&
wymagany przez standard. Ta różnica jest znacząca dla każdego, kto próbuje zastąpić funkcjędo_length()
wirtualną .
CRT
Sterta C Runtime (CRT), która jest używana dla nowych i malloc(), nie jest już prywatna. CRT używa teraz sterty procesu. Oznacza to, że sterta nie zostanie zniszczona, gdy biblioteka DLL zostanie zwolniona, dlatego biblioteki DLL, które statycznie łączą się ze statycznie z CRT, muszą zapewnić, że pamięć przydzielona przez kod DLL zostanie wyczyszczona przed jego zwolnieniem.
Funkcja
iscsymf()
jest asercyjna z wartościami ujemnymi.Struktura została zmieniona
threadlocaleinfostruct
, aby uwzględnić zmiany w funkcjach ustawień regionalnych.Funkcje CRT, które mają odpowiednie funkcje wewnętrzne, takie jak
memxxx()
,strxxx()
są usuwane z intrin.h. Jeśli dołączono tylko intrin.h tylko dla tych funkcji, musisz teraz dołączyć odpowiednie nagłówki CRT.
MFC i ATL
Usunięto obsługę łączenia (afxcomctl32.h); w związku z tym wszystkie metody zdefiniowane w zostały
<afxcomctl32.h>
usunięte. Pliki<afxcomctl32.h>
nagłówka i<afxcomctl32.inl>
zostały usunięte.Zmieniono nazwę na
CDockablePane::RemoveFromDefaultPaneDividier
CDockablePane::RemoveFromDefaultPaneDivider
.Zmieniono podpis funkcji LPCTSTR, w związku z
CFileDialog::SetDefExt
czym mają wpływ kompilacje Unicode.Usunięto przestarzałe kategorie śledzenia ATL.
Zmieniono podpis ,
CBasePane::MoveWindow
aby wykonać polecenieconst CRect
.Zmieniono podpis .
CMFCEditBrowseCtrl::EnableBrowseButton
Usunięto właściwości
m_fntTabs
im_fntTabsBold
z klasyCMFCBaseTabCtrl
.Dodano parametr do
CMFCRibbonStatusBarPane
konstruktorów. (Jest to parametr domyślny, więc nie jest to przerywanie źródła).Dodano parametr do konstruktora
CMFCRibbonCommandsListBox
. (Jest to parametr domyślny, więc nie jest to przerywanie źródła).Usunięto
AFXTrackMouse
interfejs API (i powiązany czasomierz proc). Zamiast tego użyj interfejsu API Win32TrackMouseEvent
.Dodano parametr do konstruktora
CFolderPickerDialog
. (Jest to parametr domyślny, więc nie jest to przerywanie źródła).CFileStatus
zmieniono rozmiar struktury:m_attribute
element członkowski zmienił się z BYTE na DWORD (aby był zgodny z wartością zwróconą zGetFileAttributes
).CRichEditCtrl
iCRichEditView
używaj MSFTEDIT_CLASS (kontrolka RichEdit 4.1) zamiast RICHEDIT_CLASS (kontrolka RichEdit 3.0) w kompilacjach Unicode.Usunięto
AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground
, ponieważ jest to zawsze prawda w systemach Windows Vista, Windows 7 i Windows 8.Usunięto
AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable
, ponieważ jest to zawsze prawda w systemach Windows Vista, Windows 7 i Windows 8.Usunięto
AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea
element . Wywoływanie interfejsu API systemu Windows bezpośrednio w systemach Windows Vista, Windows 7 i Windows 8.Usunięto
AFX_GLOBAL_DATA::DwmDefWindowProc
element . Wywoływanie interfejsu API systemu Windows bezpośrednio w systemach Windows Vista, Windows 7 i Windows 8.Zmieniono
AFX_GLOBAL_DATA::DwmIsCompositionEnabled
nazwę na , abyIsDwmCompositionEnabled
wyeliminować kolizję nazw.Zmieniono identyfikatory dla kilku wewnętrznych czasomierzy MFC i przeniesiono definicje do afxres.h (AFX_TIMER_ID_*).
Zmieniono podpis
OnExitSizeMove
metody tak, aby zgodziła się z makrem ON_WM_EXITSIZEMOVE:CFrameWndEx
CMDIFrameWndEx
CPaneFrameWnd
Zmieniono nazwę i podpis
OnDWMCompositionChanged
, aby wyrazić zgodę na makro ON_WM_DWMCOMPOSITIONCHANGED:CFrameWndEx
CMDIFrameWndEx
CPaneFrameWnd
Zmieniono podpis
OnMouseLeave
metody tak, aby zgodziła się z makrem ON_WM_MOUSELEAVE:CMFCCaptionBar
CMFCColorBar
CMFCHeaderCtrl
CMFCProperySheetListBox
CMFCRibbonBar
CMFCRibbonPanelMenuBar
CMFCRibbonRichEditCtrl
CMFCSpinButtonCtrl
CMFCToolBar
ReplaceThisTextCMFCToolBarComboBoxEdit
CMFCToolBarEditCtrl
CMFCAutoHideBar
Zmieniono podpis
OnPowerBroadcast
, aby zaakceptować makro ON_WM_POWERBROADCAST:CFrameWndEx
CMDIFrameWndEx
Zmieniono podpis
OnStyleChanged
w celu zaakceptowania makra ON_WM_STYLECHANGED:CMFCListCtrl
CMFCStatusBar
Zmieniono nazwę metody
FontFamalyProcFonts
wewnętrznej naFontFamilyProcFonts
.Usunięto wiele globalnych obiektów statycznych
CString
, aby wyeliminować przecieki pamięci w niektórych sytuacjach (zastąpione #defines) oraz następujące zmienne składowe klasy: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
Zmieniono podpis i
CKeyboardManager::ShowAllAccelerators
usunięto parametr ogranicznika akceleratora.Dodano
CPropertyPage::GetParentSheet
element , i wCPropertyPage
klasie wywołaj ją zamiastGetParent
, aby uzyskać poprawne okno arkusza nadrzędnego, które może być oknem rodzica lub dziadka doCPropertyPage
. Może być konieczne zmianę kodu w celu wywołaniaGetParentSheet
metody zamiastGetParent
.Naprawiono niezrównoważone ostrzeżenie (wypychanie) #pragma w usłudze ATLBASE. H, co spowodowało nieprawidłowe wyłączenie ostrzeżeń. Ostrzeżenia te są teraz poprawnie włączone po atLBASE. H został przeanalizowany.
Przeniesiono metody związane z D2D z AFX_GLOBAL_DATA do _AFX_D2D_STATE:
GetDirectD2dFactory
GetWriteFactory
GetWICFactory
InitD2D
ReleaseD2DRefs
IsD2DInitialized
D2D1MakeRotateMatrix
Zamiast wywoływać, na przykład ,
afxGlobalData.IsD2DInitialized
wywołaj metodęAfxGetD2DState->IsD2DInitialized
.
Usunięto przestarzałe atl*. Pliki CPP z folderu \atlmfc\include\.
Przeniesiono
afxGlobalData
inicjowanie na żądanie zamiast w czasie inicjowania CRT, aby spełnićDLLMain
wymagania.Dodano metodę
RemoveButtonByIndex
CMFCOutlookBarPane
do klasy .Poprawiono
CMFCCmdUsageCount::IsFreqeuntlyUsedCmd
doIsFrequentlyUsedCmd
.Poprawiono kilka wystąpień elementu
RestoreOriginalstate
doRestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane)
.Usunięto nieużywane metody z
CDockablePane
:SetCaptionStyle
, ,IsDrawCaption
IsHideDisabledButtons
,GetRecentSiblingPaneInfo
iCanAdjustLayout
.Usunięto
CDockablePane
statyczne zmiennem_bCaptionText
składowe im_bHideDisabledButtons
.Dodano metodę zastąpienia
DeleteString
doCMFCFontComboBox
metody .Usunięto nieużywane metody z
CPane
klasy :GetMinLength
iIsLastPaneOnLastRow
.Zmieniono
CPane::GetDockSiteRow(CDockingPanesRow *)
nazwę naCPane::SetDockSiteRow
.
Zmiany powodujące niezgodność programu Visual Studio 2010
Compiler
Słowo
auto
kluczowe ma nowe znaczenie domyślne. Ponieważ użycie starego znaczenia jest rzadkie, większość aplikacji nie będzie miała wpływu na tę zmianę.static_assert
Nowe słowo kluczowe zostanie wprowadzone, co spowoduje konflikt nazw, jeśli w kodzie istnieje już identyfikator o tej nazwie.Obsługa nowej notacji lambda wyklucza obsługę kodowania niekwestionowanego identyfikatora GUID w atrybucie UUID języka IDL.
Program .NET Framework 4 wprowadza koncepcję uszkodzonych wyjątków stanu, które są wyjątkami, które pozostawiają proces w nieodwracalnym stanie uszkodzonym. Domyślnie nie można przechwycić uszkodzonego wyjątku stanu, nawet w przypadku opcji kompilatora /EHa, która przechwytuje wszystkie inne wyjątki. Aby jawnie przechwycić uszkodzony wyjątek stanu, użyj instrukcji __try-__except. Możesz też zastosować atrybut [HandledProcessCorruptedStateExceptions], aby umożliwić funkcji przechwytywanie uszkodzonych wyjątków stanu. Ta zmiana dotyczy głównie programistów systemowych, którzy mogą mieć możliwość przechwycenia uszkodzonego wyjątku stanu. Osiem wyjątków to 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. Aby uzyskać więcej informacji na temat tych wyjątków, zobacz makro GetExceptionCode .
Poprawiona
/GS
opcja kompilatora chroni przed przekroczeniem buforu bardziej kompleksowo niż we wcześniejszych wersjach. Ta wersja może wstawić dodatkowe kontrole zabezpieczeń w stosie, który może zmniejszyć wydajność. Użyj nowego__declspec(safebuffers)
słowa kluczowego, aby poinstruować kompilatora, aby nie wstawiał kontroli zabezpieczeń dla określonej funkcji.Jeśli kompilujesz zarówno opcje kompilatora
/GL
(Optymalizacja całego programu) i/clr
(kompilacja/GL
środowiska uruchomieniowego języka wspólnego), opcja zostanie zignorowana. Ta zmiana została wprowadzona, ponieważ kombinacja opcji kompilatora przyniosła niewielkie korzyści. W wyniku tej zmiany wydajność kompilacji zostanie zwiększona.Domyślnie obsługa trigrafów jest wyłączona w programie Visual Studio 2010. Użyj opcji kompilatora
/Zc:trigraphs
, aby włączyć obsługę trigrafów. Trójznak składa się z dwóch kolejnych znaków zapytania ("??"), po których następuje unikatowy trzeci znak. Kompilator zastępuje trigraf odpowiednim znakiem interpunkcyjnym. Na przykład kompilator zastępuje??=
trigraf znakiem "#". Użyj trigrafów w plikach źródłowych języka C, które używają zestawu znaków, który nie zawiera wygodnych reprezentacji graficznych dla niektórych znaków interpunkcyjnych.Konsolidator nie obsługuje już optymalizacji pod kątem systemu Windows 98. Opcja
/OPT
(Optymalizacje) generuje błąd czasu kompilacji, jeśli określisz/OPT:WIN98
wartość lub/OPT:NOWIN98
.Domyślne opcje kompilatora określone przez właściwości systemu kompilacji RuntimeLibrary i DebugInformationFormat zostały zmienione. Domyślnie te właściwości kompilacji są określane w projektach tworzonych przez wersje visual C++ od 7.0 do 10.0. Jeśli przeprowadzisz migrację projektu utworzonego przez program Visual C++ 6.0, rozważ określenie wartości dla tych właściwości.
W programie Visual Studio 2010 runtimeLibrary = MultiThreaded (
/MD
) i DebugInformationFormat = ProgramDatabase (/Zi
). W programie Visual C++ 9.0 runtimeLibrary = MultiThreaded (/MT
) i DebugInformationFormat = Disabled.
CLR
- Kompilatory języka Microsoft C# i Visual Basic mogą teraz utworzyć żaden podstawowy zestaw międzyoperacyjny (no-PIA). Zestaw no-PIA może używać typów COM bez wdrażania odpowiedniego podstawowego zestawu międzyoperaowego (PIA). W przypadku korzystania z zestawów bez pia utworzonych przez program Visual C# lub Visual Basic należy odwołać się do zestawu PIA w poleceniu kompilacji przed odwołaniem do dowolnego zestawu bez pia, który korzysta z biblioteki.
Projekty visual Studio C++ i program MSBuild
Projekty visual Studio C++ są teraz oparte na narzędziu MSBuild. W związku z tym pliki projektu używają nowego formatu pliku XML i sufiksu pliku .vcxproj. Program Visual Studio 2010 automatycznie konwertuje pliki projektu z wcześniejszych wersji programu Visual Studio na nowy format pliku. Problem dotyczy istniejącego projektu, jeśli zależy od poprzedniego narzędzia kompilacji, VCBUILD.exe lub sufiksu pliku projektu vcproj.
We wcześniejszych wersjach program Visual C++ obsługiwał późną ocenę arkuszy właściwości. Na przykład nadrzędny arkusz właściwości może zaimportować podrzędny arkusz właściwości, a obiekt nadrzędny może użyć zmiennej zdefiniowanej w elemecie podrzędnym w celu zdefiniowania innych zmiennych. Opóźniona ocena umożliwiła elementowi nadrzędnego używanie zmiennej podrzędnej jeszcze przed zaimportowanie podrzędnego arkusza właściwości. W programie Visual Studio 2010 nie można użyć zmiennej arkusza projektu przed jej zdefiniowaną, ponieważ program MSBuild obsługuje tylko wczesną ocenę.
IDE
Okno dialogowe kończenia działania aplikacji nie kończy już aplikacji. W poprzednich wersjach, gdy
abort()
funkcja orterminate()
zamknęła kompilację detaliczną aplikacji, biblioteka czasu wykonywania języka C wyświetliła komunikat o zakończeniu działania aplikacji w oknie konsoli lub oknie dialogowym. Komunikat powiedział po części: "Ta aplikacja zażądała, aby środowisko uruchomieniowe zakończyło je w nietypowy sposób. Aby uzyskać więcej informacji, skontaktuj się z zespołem pomocy technicznej aplikacji. Komunikat o zakończeniu działania aplikacji był nadmiarowy, ponieważ system Windows wyświetlił bieżącą procedurę obsługi zakończenia, która była zwykle Raportowanie błędów systemu Windows (Dr. Watson) okno dialogowe lub debuger programu Visual Studio. Począwszy od programu Visual Studio 2010 biblioteka czasu wykonywania języka C nie wyświetla komunikatu. Ponadto środowisko uruchomieniowe uniemożliwia zakończenie aplikacji przed uruchomieniem debugera. Jest to zmiana powodująca niezgodność tylko wtedy, gdy zależysz od poprzedniego zachowania komunikatu o zakończeniu działania aplikacji.W szczególności w przypadku programu Visual Studio 2010 funkcja IntelliSense nie działa w przypadku kodu lub atrybutów języka C++/interfejsu wiersza polecenia, funkcja Znajdź wszystkie odwołania nie działa w przypadku zmiennych lokalnych, a model kodu nie pobiera nazw typów z importowanych zestawów ani nie rozpoznaje typów do ich w pełni kwalifikowanych nazw.
Biblioteki
Klasa SafeInt jest uwzględniona w języku Visual C++ i nie jest już w osobnym pobieraniu. Jest to zmiana powodująca niezgodność tylko wtedy, gdy utworzono klasę o nazwie "SafeInt".
Model wdrażania bibliotek nie używa już manifestów do znalezienia konkretnej wersji biblioteki linków dynamicznych. Zamiast tego nazwa każdej biblioteki linków dynamicznych zawiera jego numer wersji i używasz tej nazwy do zlokalizowania biblioteki.
W poprzednich wersjach programu Visual Studio można ponownie skompilować biblioteki czasu wykonywania. Program Visual Studio 2010 nie obsługuje już tworzenia własnych kopii plików bibliotek czasu wykonywania języka C.
Standardowa biblioteka
Nagłówek
<iterator>
nie jest już automatycznie dołączany przez wiele innych plików nagłówków. Zamiast tego dołącz ten nagłówek jawnie, jeśli potrzebujesz obsługi autonomicznych iteratorów zdefiniowanych w nagłówku. Problem dotyczy istniejącego projektu, jeśli zależy od poprzedniego narzędzia kompilacji, VCBUILD.exe lub sufiksu pliku projektu vcproj.iterator.W nagłówku
<algorithm>
checked_*
funkcje iunchecked_*
są usuwane. W nagłówku<iterator>
>checked_iterator
klasa zostanie usunięta, aunchecked_array_iterator
klasa została dodana.Konstruktor
CComPtr::CComPtr(int)
jest usuwany. Ten konstruktor zezwolił naCComPtr
konstruowanie obiektu z makra NULL, ale był niepotrzebny i zezwalał na niesensowne konstrukcje z liczb całkowitych innych niż zero.Można
CComPtr
nadal utworzyć obiekt z wartości NULL, która jest zdefiniowana jako 0, ale zakończy się niepowodzeniem, jeśli zostanie skonstruowana z liczby całkowitej innej niż literał 0. Użycie w zamian parametrunullptr
.Usunięto następujące
ctype
funkcje składowe:ctype::_Do_narrow_s
, ,ctype::_narrow_s
ctype::_Do_widen_s
,ctype::_widen_s
. Jeśli aplikacja używa jednej z tych funkcji składowych, należy zastąpić ją odpowiednią wersją niezabezpieczoną:ctype::do_narrow
, ,ctype::narrow
ctype::do_widen
,ctype::widen
.
Biblioteki CRT, MFC i ATL
Obsługa została usunięta dla użytkowników w celu utworzenia bibliotek CRT, MFC i ATL. Na przykład nie podano odpowiedniego pliku NMAKE. Jednak użytkownicy nadal mają dostęp do kodu źródłowego dla tych bibliotek. Dokument opisujący opcje programu MSBuild używane przez firmę Microsoft do kompilowania tych bibliotek prawdopodobnie zostanie opublikowany w blogu zespołu visual C++.
Obsługa protokołu MFC dla IA64 została usunięta. Jednak wsparcie dla CRT i ATL w IA64 jest nadal zapewniane.
Reguły domyślne nie są już używane w plikach definicji modułu MFC (.def). Ta zmiana oznacza, że reguły nie będą się różnić między wersjami pomocniczymi, a zgodność binarna dodatków Service Pack i szybkie poprawki wydania inżynieryjne zostaną ulepszone.
Nowa funkcja wirtualna została dodana do
CDocTemplate
klasy. Ta nowa funkcja wirtualna to klasa CDocTemplate. Poprzednia wersja programuOpenDocumentFile
miała dwa parametry. Nowa wersja ma trzy parametry. Aby obsługiwać menedżera ponownego uruchamiania, każda klasa pochodząca zCDocTemplate
klasy musi zaimplementować wersję, która ma trzy parametry. Nowy parametr tobAddToMRU
.
Makra i zmienne środowiskowe
- Zmienna środowiskowa __MSVCRT_HEAP_SELECT nie jest już obsługiwana. Ta zmienna środowiskowa jest usuwana i nie ma zamiany.
Microsoft Macro Assembler — odwołanie
- Kilka dyrektyw zostało usuniętych z kompilatora odwołań makr firmy Microsoft. Usunięte dyrektywy to
.186
, ,.286
,.286P
.287
,.8086
, ,.8087
i.NO87
.
Zmiany powodujące niezgodność programu Visual Studio 2008
Compiler
Platformy Windows 95, Windows 98, Windows ME i Windows NT nie są już obsługiwane. Te systemy operacyjne zostały usunięte z listy platform docelowych.
Kompilator nie obsługuje już wielu atrybutów, które zostały bezpośrednio skojarzone z serwerem ATL. Następujące atrybuty nie są już obsługiwane:
perf_counter
perf_object
perfmon
request_handler
soap_handler
soap_header
soap_method
tag_name
Projekty Visual Studio C++
Podczas uaktualniania projektów z poprzednich wersji programu Visual Studio może być konieczne zmodyfikowanie makr WINVER i _WIN32_WINNT tak, aby były większe lub równe 0x0500.
Począwszy od programu Visual Studio 2008, nowy kreator projektu nie ma możliwości utworzenia projektu C++ SQL Server. Projekty programu SQL Server utworzone przy użyciu starszej wersji programu Visual Studio będą nadal kompilować i działać poprawnie.
Plik nagłówka interfejsu API systemu Windows Winable.h został usunięty. Uwzględnij zamiast tego winuser.h.
Biblioteka interfejsu API systemu Windows Rpcndr.lib została usunięta. Zamiast tego połącz z rpcrt4.lib.
CRT
Usunięto obsługę systemów Windows 95, Windows 98, Windows Millennium Edition i Windows NT 4.0.
Usunięto następujące zmienne globalne:
_osplatform
_osver
_winmajor
_winminor
_winver
Następujące funkcje zostały usunięte. Użyj funkcji
GetVersion
interfejsu API systemu Windows lubGetVersionEx
zamiast tego:_get_osplatform
_get_osver
_get_winmajor
_get_winminor
_get_winver
Składnia adnotacji SAL została zmieniona. Aby uzyskać więcej informacji, zobacz Adnotacje SAL.
Filtr IEEE obsługuje teraz zestaw instrukcji SSE 4.1. Aby uzyskać więcej informacji, zobacz _fpieee_flt_fpieee_flt.
Biblioteki czasu wykonywania języka C dostarczane z programem Visual Studio nie są już zależne od systemowej biblioteki DLL msvcrt.dll.
Standardowa biblioteka
Usunięto obsługę systemów Windows 95, Windows 98, Windows Millennium Edition i Windows NT 4.0.
Podczas kompilowania w trybie debugowania przy użyciu _HAS_ITERATOR_DEBUGGING zdefiniowanych (zastąpionych przez _ITERATOR_DEBUG_LEVEL po programie Visual Studio 2010) aplikacja będzie teraz potwierdzać, gdy iterator próbuje zwiększać lub dekrementować granice bazowego kontenera.
Zmienna składowa c klasy stosu jest teraz zadeklarowana jako chroniona. Wcześniej ta zmienna składowa została zadeklarowana publicznie.
Zachowanie
money_get::do_get
metody uległo zmianie. Wcześniej podczas analizowania kwoty pieniężnej z większą liczbie cyfr ułamkowych niż są wywoływane przezfrac_digits
program ,do_get
używane do ich użycia wszystkich.do_get
Teraz zatrzymuje analizowanie po użyciu najwyżejfrac_digits
znaków.
ATL
Nie można skompilować atl bez zależności od CRT. We wcześniejszych wersjach programu Visual Studio można użyć #define ATL_MIN_CRT, aby projekt ATL był minimalnie zależny od CRT. W programie Visual Studio 2008 wszystkie projekty ATL są minimalnie zależne od CRT niezależnie od tego, czy ATL_MIN_CRT jest zdefiniowana.
Baza kodu serwera ATL została wydana jako udostępniony projekt źródłowy w pliku CodePlex i nie jest zainstalowana w ramach programu Visual Studio. Klasy kodowania i dekodowania danych z funkcji atlenc.h i narzędzi i klas z atlutil.h i atlpath.h zostały zachowane i są teraz częścią biblioteki ATL. Kilka plików skojarzonych z serwerem ATL nie jest już częścią programu Visual Studio.
Niektóre funkcje nie są już dołączone do biblioteki DLL. Nadal znajdują się one w bibliotece importu. Nie będzie to miało wpływu na kod, który statycznie używa funkcji. Będzie to miało wpływ tylko na kod, który dynamicznie używa tych funkcji.
Makra PROP_ENTRY i PROP_ENTRY_EX zostały wycofane i zastąpione makrami PROP_ENTRY_TYPE i PROP_ENTRY_TYPE_EX ze względów bezpieczeństwa.
Klasy współdzielone ATL/MFC
Nie można skompilować atl bez zależności od CRT. We wcześniejszych wersjach programu Visual Studio można użyć
#define ATL_MIN_CRT
polecenia , aby projekt ATL był minimalnie zależny od CRT. W programie Visual Studio 2008 wszystkie projekty ATL są minimalnie zależne od CRT niezależnie od tego, czy ATL_MIN_CRT jest zdefiniowana.Baza kodu serwera ATL została wydana jako udostępniony projekt źródłowy w pliku CodePlex i nie jest zainstalowana w ramach programu Visual Studio. Klasy kodowania i dekodowania danych z funkcji atlenc.h i narzędzi i klas z atlutil.h i atlpath.h zostały zachowane i są teraz częścią biblioteki ATL. Kilka plików skojarzonych z serwerem ATL nie jest już częścią programu Visual Studio.
Niektóre funkcje nie są już dołączone do biblioteki DLL. Nadal znajdują się one w bibliotece importu. Nie będzie to miało wpływu na kod, który statycznie używa funkcji. Będzie to miało wpływ tylko na kod, który dynamicznie używa tych funkcji.
MFC
CTime
Klasa:CTime
Klasa akceptuje teraz daty od 1.1.1.1.1900 C.E. zamiast 1/1/1970 C.E.Kolejność tabulatorów kontrolek w oknach dialogowych MFC: prawidłowa kolejność tabulacji wielu kontrolek w oknie dialogowym MFC jest zakłócona, jeśli kontrolka ActiveX MFC zostanie wstawiona w kolejności tabulacji. Ta zmiana naprawia ten problem.
Na przykład utwórz aplikację dialogową MFC z kontrolką ActiveX i kilkoma kontrolkami edycji. Umieść kontrolkę ActiveX w środku kolejności tabulacji kontrolek edycji. Uruchom aplikację, kliknij kontrolkę edycji, której kolejność tabulacji znajduje się po kontrolce ActiveX, a następnie na karcie . Przed tą zmianą fokus przeszedł do kontrolki edycji po kontrolce ActiveX zamiast następnej kontrolki edycji w kolejności tabulacji.
CFileDialog
Klasa: Szablony niestandardowe dlaCFileDialog
klasy nie mogą być automatycznie przenoszone do systemu Windows Vista. Są one nadal użyteczne, ale nie będą miały dodatkowej funkcjonalności ani okien dialogowych stylu systemu Windows Vista.CWnd
Klasa iCFrameWnd
klasa: metoda została usuniętaCWnd::GetMenuBarInfo
.Metoda
CFrameWnd::GetMenuBarInfo
jest teraz metodą niewirtuacyjną. Aby uzyskać więcej informacji, zobacz GetMenuBarInfo Function in the Windows SDK (Funkcja GetMenuBarInfo w zestawie Windows SDK).Obsługa interfejsu MFC ISAPI: MFC nie obsługuje już tworzenia aplikacji za pomocą internetowego interfejsu programowania aplikacji (ISAPI). Jeśli chcesz utworzyć aplikację ISAPI, wywołaj rozszerzenia ISAPI bezpośrednio.
Przestarzałe interfejsy API ANSI: wersje ANSI kilku metod MFC są przestarzałe. Użyj wersji Unicode tych metod w przyszłych aplikacjach. Aby uzyskać więcej informacji, zobacz Wymagania dotyczące kompilacji dla typowych kontrolek systemu Windows Vista.
Zmiany powodujące niezgodność programu Visual Studio 2005
CRT
Wiele funkcji zostało przestarzałych. Zobacz Przestarzałe funkcje CRT.
Wiele funkcji weryfikuje teraz parametry, zatrzymując wykonywanie, jeśli podano nieprawidłowe parametry. Ta walidacja może spowodować przerwanie kodu, który przekazuje nieprawidłowe parametry i opiera się na funkcji ignorując je lub po prostu zwracając kod błędu. Zobacz Walidacja parametrów.
Wartość deskryptora pliku -2 jest teraz używana do wskazania, że
stdout
dane wyjściowe istderr
nie są dostępne, na przykład w aplikacji systemu Windows, która nie ma okna konsoli. Użyta poprzednia wartość to -1. Aby uzyskać więcej informacji, zobacz _fileno.Usunięto biblioteki CRT z jednym wątkiem (libc.lib i libcd.lib). Użyj wielowątowych bibliotek CRT. Flaga kompilatora
/ML
nie jest już obsługiwana. Nieblokujące wersje niektórych funkcji zostały dodane w przypadkach, gdy różnica wydajności między kodem wielowątkowym a kodem jednowątkowym jest potencjalnie znacząca.Przeciążenie pow, double pow(int, int) zostało usunięte w celu lepszego zachowania zgodności ze standardem.
Specyfikator formatu %n nie jest już obsługiwany domyślnie w żadnej rodzinie funkcji printf, ponieważ jest z natury niezabezpieczony. W przypadku napotkania elementu %n domyślne zachowanie polega na wywołaniu nieprawidłowej procedury obsługi parametrów. Aby włączyć obsługę produktu %n, użyj polecenia
_set_printf_count_output
(zobacz_get_printf_count_output
również ).sprintf
teraz drukuje znak ujemny zeru ze znakiem.swprintf
została zmieniona tak, aby była zgodna ze standardem; teraz wymaga parametru rozmiaru. Postać bez parametruswprintf
rozmiaru została przestarzała._set_security_error_handler
został usunięty. Usuń wszystkie wywołania tej funkcji; domyślna procedura obsługi jest znacznie bezpieczniejszym sposobem radzenia sobie z błędami zabezpieczeń.time_t
jest teraz wartością 64-bitową (chyba że _USE_32BIT_TIME_T jest zdefiniowana)._wspawn
Funkcja_spawn
, pozostawiaerrno
teraz nietkniętą wartość powodzenia, jak określono w standardzie C.Funkcja RTC domyślnie używa znaków szerokich.
Funkcje obsługi wyrazów sterowania zmiennoprzecinkowego zostały przestarzałe dla aplikacji skompilowanych za pomocą
/CLR
polecenia lub/CLR:PURE
. Objęte funkcje to_clear87
, ,_clearfp
,_control87
,_controlfp
_fpreset
, ,_status87
, ._statusfp
Możesz wyłączyć ostrzeżenie o wycofaniu, definiując _CRT_MANAGED_FP_NO_DEPRECATE, ale użycie tych funkcji w kodzie zarządzanym jest nieprzewidywalne i nieobsługiwane.Niektóre funkcje zwracają teraz wskaźniki const. Stare, inne niż const zachowanie można przywrócić, definiując _CONST_RETURN. Funkcje, których dotyczy problem, są
memchr, wmemchr
strchr, wcschr, _mbschr, _mbschr_l
strpbrk, wcspbrk, _mbspbrk, _mbspbrk_l
strrchr, wcsrchr, _mbsrchr, _mbsrchr_l
strstr, wcsstr, _mbsstr, _mbsstr_l
Podczas łączenia z Setargv.obj lub Wsetargv.obj nie można już pominąć rozszerzania symbolu wieloznacznego w wierszu polecenia, umieszczając go w podwójnych cudzysłowach. Aby uzyskać więcej informacji, zobacz Rozwijanie argumentów wieloznacznych.
Standardowa biblioteka (2005)
Klasa wyjątku (znajdująca się w nagłówku
<exception>
) została przeniesiona dostd
przestrzeni nazw. W poprzednich wersjach ta klasa znajdowała się w globalnej przestrzeni nazw. Aby usunąć wszelkie błędy wskazujące, że nie można odnaleźć klasy wyjątków, dodaj następującą instrukcję using do kodu:using namespace std;
Podczas wywoływania
valarray::resize()
metody zawartośćvalarray
obiektu zostanie utracona i zostanie zamieniona na wartości domyślne. Metodaresize()
ma na celu ponowne inicjowanievalarray
zamiast dynamicznie rosnąć jak wektor.Iteratory debugowania: aplikacje utworzone przy użyciu wersji debugowania biblioteki C-Runtime i używające iteratorów niepoprawnie mogą zaczynać widzieć aseracje w czasie wykonywania. Aby wyłączyć te potwierdzenia, należy zdefiniować _HAS_ITERATOR_DEBUGGING (zastąpione przez
_ITERATOR_DEBUG_LEVEL
program Visual Studio 2010) do 0. Aby uzyskać więcej informacji, zobacz Debugowanie obsługi iteratora
Zmiany powodujące niezgodność w programie Visual C++ .NET 2003
Compiler
Nawiasy zamykające są teraz wymagane dla zdefiniowanej dyrektywy preprocesora (C2004).
Jawne specjalizacje nie znajdują już parametrów szablonu z szablonu podstawowego (błąd kompilatora C2146).
Dostęp do chronionego elementu członkowskiego (n) można uzyskać tylko za pośrednictwem funkcji składowej klasy (B), która dziedziczy z klasy (A), której elementem członkowskim (n) jest składowa (błąd kompilatora C2247).
Ulepszone kontrole ułatwień dostępu w kompilatorze wykrywają teraz niedostępne klasy bazowe (błąd kompilatora C2248).
Nie można złapać wyjątku, jeśli destruktor i/lub konstruktor kopiowania jest niedostępny (C2316).
Domyślne argumenty wskaźników do funkcji nie są już dozwolone (błąd kompilatora C2383).
Nie można zainicjować statycznej składowej danych za pośrednictwem klasy pochodnej (błąd kompilatora C2477).
Inicjowanie elementu
typedef
nie jest dozwolone przez standard, a teraz generuje błąd kompilatora (błąd kompilatora C2513).bool
jest teraz odpowiednim typem (błąd kompilatora C2632).Funkcja UDC może teraz tworzyć niejednoznaczność z przeciążonymi operatorami (C2666).
Więcej wyrażeń jest teraz uważanych za prawidłowe stałe wskaźnika null (błąd kompilatora C2668).
Szablon<> jest teraz wymagany w miejscach, w których kompilator wcześniej go sugerował (błąd kompilatora C2768).
Jawna specjalizacja funkcji składowej poza klasą jest nieprawidłowa, jeśli funkcja została już jawnie wyspecjalizowana za pomocą specjalizacji klasy szablonu (błąd kompilatora C2910).
Parametry szablonu innego niż typ zmiennoprzecinkowy nie są już dozwolone (błąd kompilatora C2993).
Szablony klas nie są dozwolone jako argumenty typu szablonu (C3206).
Nazwy funkcji znajomych nie są już wprowadzane do zawierającej przestrzeń nazw (błąd kompilatora C3767).
Kompilator nie będzie już akceptować dodatkowych przecinków w makrze (C4002).
Obiekt typu POD skonstruowany z inicjatorem formularza () zostanie zainicjowany domyślnie (C4345).
nazwa_typu jest teraz wymagana, jeśli nazwa zależna ma być traktowana jako typ (ostrzeżenie kompilatora (poziom 1) C4346).
Funkcje, które zostały nieprawidłowo uznane za specjalizacje szablonów, nie są już brane pod uwagę (C4347).
Statyczne składowe danych nie mogą być inicjowane za pośrednictwem klasy pochodnej (C4356).
Specjalizacja szablonu klasy musi być zdefiniowana, zanim będzie używana w typie zwracanym (ostrzeżenie kompilatora (poziom 3) C4686).
Kompilator zgłasza teraz niemożliwy do osiągnięcia kod (C4702).