Riwayat perubahan Microsoft C/C++ 2003 - 2015
Artikel ini menjelaskan semua perubahan yang melanggar dari Visual Studio 2015 kembali ke Visual Studio 2003, dan dalam artikel ini istilah "perilaku baru" atau "sekarang" merujuk ke Visual Studio 2015 dan yang lebih baru. Istilah "perilaku lama" dan "sebelum" mengacu pada Visual Studio 2013 dan rilis sebelumnya.
Untuk informasi tentang versi terbaru Visual Studio, lihat Apa yang baru untuk C++ di Visual Studio dan peningkatan kesuaian C++ di Visual Studio.
Catatan
Tidak ada perubahan pemecahan biner antara Visual Studio 2015 dan Visual Studio 2017.
Saat meningkatkan ke versi baru Visual Studio, Anda mungkin mengalami kesalahan kompilasi dan/atau runtime dalam kode yang sebelumnya dikompilasi dan dijalankan dengan benar. Perubahan dalam versi baru yang menyebabkan masalah tersebut dikenal sebagai perubahan yang melanggar, dan biasanya diperlukan oleh modifikasi dalam standar bahasa C++, tanda tangan fungsi, atau tata letak objek dalam memori.
Untuk menghindari kesalahan run-time yang sulit dideteksi dan didiagnosis, kami sarankan Anda tidak pernah menautkan secara statis ke biner yang dikompilasi dengan menggunakan versi pengompilasi yang berbeda. Selain itu, saat Anda meningkatkan proyek EXE atau DLL, pastikan untuk meningkatkan pustaka yang ditautkannya. Jangan meneruskan jenis CRT (C Runtime) atau C++ Standard Library (C++ Standard Library) antar biner, termasuk DLL, yang dikompilasi dengan menggunakan versi kompiler yang berbeda. Untuk informasi selengkapnya, lihat Potensi Kesalahan Melewati Objek CRT Di Seluruh Batas DLL.
Anda tidak boleh menulis kode yang bergantung pada tata letak tertentu untuk objek yang bukan antarmuka COM atau objek POD. Jika Anda menulis kode tersebut, maka Anda harus memastikan bahwa kode tersebut berfungsi setelah Anda meningkatkan. Untuk informasi selengkapnya, lihat Portabilitas Di Batas ABI.
Selain itu, peningkatan berkelanjutan pada kesuaian kompilator terkadang dapat mengubah bagaimana pengkompilasi memahami kode sumber Anda yang ada. Misalnya, Anda mungkin menemukan kesalahan baru atau berbeda selama build Anda, atau bahkan perbedaan perilaku dalam kode yang sebelumnya dibangun dan tampaknya berjalan dengan benar. Meskipun peningkatan ini tidak melanggar perubahan seperti yang dibahas dalam dokumen ini, Anda mungkin perlu membuat perubahan pada kode sumber Anda untuk mengatasi masalah ini:
Perubahan Kesuaian Visual Studio 2015
Pustaka Runtime C (CRT)
Perubahan Umum
Biner yang direfaktor
Pustaka CRT telah direfaktor menjadi dua biner berbeda: Universal CRT (ucrtbase), yang berisi sebagian besar fungsionalitas standar, dan Pustaka Runtime VC (vcruntime). Pustaka vcruntime berisi fungsionalitas terkait kompilator seperti penanganan pengecualian, dan intrinsik. Jika Anda menggunakan pengaturan proyek default, perubahan ini tidak memengaruhi Anda karena linker menggunakan pustaka default baru secara otomatis. Jika Anda telah mengatur properti Linker proyek Abaikan Semua Pustaka Default ke Ya atau Anda menggunakan
/NODEFAULTLIB
opsi linker pada baris perintah, maka Anda harus memperbarui daftar pustaka Anda (di properti Dependensi Tambahan) untuk menyertakan pustaka baru yang direfaktor. Ganti pustaka CRT lama (libcmt.lib
, ,libcmtd.lib
msvcrt.lib
,msvcrtd.lib
) dengan pustaka yang direfaktor yang setara. Untuk masing-masing dari dua pustaka yang direfaktor, ada versi statis (.lib) dan dinamis (.dll), dan rilis (tanpa akhiran) dan versi debug (dengan akhiran "d"). Versi dinamis memiliki pustaka impor yang Anda tautkan. Dua pustaka yang direfaktor adalah Universal CRT, khususnya ucrtbase.dll atau ucrtbase.lib, ucrtbased.dll atau ucrtbased.lib, dan pustaka runtime VC,libvcruntime.lib
versi vcruntime.dll,libvcruntimed.lib
, dan versi vcruntimed.dll. Versi di Visual Studio 2015 dan Visual Studio 2017 adalah 140. Lihat Fitur Pustaka CRT.
<locale.h>
localeconv
Fungsi
localeconv
yang dideklarasikan dalam locale.h sekarang berfungsi dengan benar ketika lokal per utas diaktifkan. Di versi pustaka sebelumnya, fungsi ini akan mengembalikanlconv
data untuk lokal global, bukan lokal utas.Jika Anda menggunakan lokal per utas, Anda harus memeriksa penggunaan Anda .
localeconv
Jika kode Anda mengasumsikan bahwa data yanglconv
dikembalikan adalah untuk lokal global, Anda harus memperbaikinya.
<math.h>
Kelebihan beban C++ fungsi pustaka matematika
Dalam versi sebelumnya,
<math.h>
didefinisikan beberapa, tetapi tidak semua, dari C++ kelebihan beban untuk fungsi pustaka matematika. Sisa kelebihan beban berada di<cmath>
header. Kode yang hanya disertakan<math.h>
dapat memiliki masalah dengan resolusi kelebihan beban fungsi. Sekarang kelebihan beban C++ telah dihapus dari<math.h>
dan hanya ditemukan di<cmath>
.Untuk mengatasi kesalahan, sertakan
<cmath>
untuk mendapatkan deklarasi fungsi yang dihapus dari<math.h>
. Fungsi-fungsi ini dipindahkan:double abs(double)
danfloat 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
danlong double
versi fungsiacos
titik mengambang , , ,acosh
,llround
atanh
atan2
cbrt
ceil
copysign
atan
cosh
cos
erf
erfc
exp
exp2
expm1
asinh
fdim
fabs
floor
fma
fmax
fmin
log10
log
log1p
llrint
lgamma
ldexp
log2
ilogb
hypot
frexp
lrint
asin
scalbln
round
fmod
nextafter
nexttoward
nearbyint
remainder
modf
remquo
sinh
scalbn
rint
lround
sqrt
tan
sin
,tanh
, , dantgamma
trunc
Jika Anda memiliki kode yang menggunakan
abs
dengan jenis titik mengambang yang hanya menyertakan<math.h>
header, versi titik mengambang tidak akan tersedia lagi. Panggilan sekarang diselesaikan keabs(int)
, bahkan dengan argumen floating point, yang menghasilkan kesalahan:warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of data
Perbaikan untuk peringatan ini adalah mengganti panggilan ke
abs
dengan versi titik mengambang dariabs
, sepertifabs
untuk argumen ganda ataufabsf
untuk argumen float, atau menyertakan<cmath>
header dan terus menggunakanabs
.Kesuaian titik mengambang
Banyak perubahan pada pustaka matematika telah dilakukan untuk meningkatkan kesamaan dengan spesifikasi IEEE-754 dan C11 Annex F sehubungan dengan input kasus khusus seperti NaN dan tak terbatas. Misalnya, input NaN yang tenang, yang sering diperlakukan sebagai kesalahan dalam versi pustaka sebelumnya, tidak lagi diperlakukan sebagai kesalahan. Lihat IEEE 754 Standard dan Annex F dari C11 Standard.
Perubahan ini tidak akan menyebabkan kesalahan waktu kompilasi, tetapi dapat menyebabkan program berulah secara berbeda dan lebih benar sesuai dengan standar.
FLT_ROUNDS
Di Visual Studio 2013, makro FLT_ROUNDS diperluas ke ekspresi konstanta, yang salah karena mode pembulatan dapat dikonfigurasi saat runtime, misalnya, dengan memanggil fesetround. Makro FLT_ROUNDS sekarang dinamis dan mencerminkan mode pembulatan saat ini dengan benar.
<new>
dan <new.h>
new
dandelete
Dalam versi pustaka sebelumnya, fungsi baru dan penghapusan operator yang ditentukan implementasi diekspor dari DLL pustaka runtime (misalnya, msvcr120.dll). Fungsi operator ini sekarang selalu ditautkan secara statis ke biner Anda, bahkan saat menggunakan DLL pustaka runtime.
Ini bukan perubahan yang melanggar untuk kode asli atau campuran (
/clr
), namun untuk kode yang dikompilasi sebagai /clr:pure, perubahan ini dapat menyebabkan kode Anda gagal dikompilasi. Jika Anda mengkompilasi kode sebagai/clr:pure
, Anda mungkin perlu menambahkan#include <new>
atau#include <new.h>
untuk mengatasi kesalahan build karena perubahan ini. Opsi/clr:pure
tidak digunakan lagi di Visual Studio 2015 dan tidak didukung di Visual Studio 2017. Kode yang perlu "murni" harus di-port ke C#.
<process.h>
_beginthread
dan_beginthreadex
Fungsi
_beginthread
dan_beginthreadex
sekarang menyimpan referensi ke modul tempat prosedur utas didefinisikan selama durasi utas. Ini membantu memastikan bahwa modul tidak dibongkar hingga utas berjalan hingga selesai.
<stdarg.h>
va_start
dan jenis referensiSaat mengkompilasi kode C++,
va_start
sekarang memvalidasi pada waktu kompilasi bahwa argumen yang diteruskan ke itu bukan jenis referensi. Argumen jenis referensi dilarang oleh Standar C++.
<stdio.h>
dan <conio.h>
Keluarga fungsi cetak dan pemindaian sekarang didefinisikan sebaris.
Definisi semua
printf
fungsi danscanf
telah dipindahkan sebaris ke ,<stdio.h>
<conio.h>
, dan header CRT lainnya. Perubahan yang melanggar ini menyebabkan kesalahan linker (LNK2019, simbol eksternal yang tidak terselesaikan) untuk program apa pun yang mendeklarasikan fungsi ini secara lokal tanpa menyertakan header CRT yang sesuai. Jika memungkinkan, Anda harus memperbarui kode untuk menyertakan header CRT (yaitu, tambahkan#include <stdio.h>
) dan fungsi sebaris, tetapi jika Anda tidak ingin mengubah kode Anda untuk menyertakan file header ini, solusi alternatifnya adalah menambahkanlegacy_stdio_definitions.lib
ke input linker Anda.Untuk menambahkan pustaka ini ke input linker Anda di IDE, buka menu konteks untuk simpul proyek, pilih Properti, lalu di kotak dialog Properti Proyek, pilih Linker, dan edit Input Linker untuk ditambahkan
legacy_stdio_definitions.lib
ke daftar yang dipisahkan titik koma.Jika proyek Anda ditautkan dengan pustaka statis yang dikompilasi dengan rilis Visual Studio lebih awal dari 2015, linker mungkin melaporkan simbol eksternal yang belum terselesaikan. Kesalahan ini mungkin mereferensikan definisi internal untuk
_iob
, ,_iob_func
atau impor terkait untuk fungsi tertentu<stdio.h>
dalam bentuk imp*. Microsoft menyarankan agar Anda mengkompilasi ulang semua pustaka statis dengan versi terbaru pengkompilasi dan pustaka C++ saat Anda meningkatkan proyek. Jika pustaka adalah pustaka pihak ketiga yang sumbernya tidak tersedia, Anda harus meminta biner yang diperbarui dari pihak ketiga atau merangkum penggunaan pustaka tersebut ke dll terpisah yang Anda kompilasi dengan versi kompilator dan pustaka yang lebih lama.Peringatan
Jika Anda menautkan dengan Windows SDK 8.1 atau yang lebih lama, Anda mungkin mengalami kesalahan simbol eksternal yang belum terselesaikan ini. Dalam hal ini, Anda harus mengatasi kesalahan dengan menambahkan legacy_stdio_definitions.lib ke input linker seperti yang dijelaskan sebelumnya.
Untuk memecahkan masalah kesalahan simbol yang belum terselesaikan, Anda dapat mencoba menggunakan
dumpbin.exe
untuk memeriksa simbol yang ditentukan dalam biner. Coba baris perintah berikut untuk melihat simbol yang ditentukan dalam pustaka.dumpbin.exe /LINKERMEMBER somelibrary.lib
mendapatkan dan _getws
Fungsi gets dan _getws telah dihapus. Fungsi gets dihapus dari Pustaka Standar C di C11 karena tidak dapat digunakan dengan aman. Fungsi _getws adalah ekstensi Microsoft yang setara dengan mendapatkan tetapi untuk string lebar. Sebagai alternatif untuk fungsi-fungsi ini, pertimbangkan penggunaan fget, fgetw, gets_s, dan _getws_s.
_cgets dan _cgetws
Fungsi _cgets dan _cgetws telah dihapus. Sebagai alternatif untuk fungsi-fungsi ini, pertimbangkan penggunaan _cgets_s dan _cgetws_s.
Pemformatan Infinity dan NaN
Dalam versi sebelumnya, infinities dan NaN akan diformat menggunakan sekumpulan string sentinel khusus MSVC.
Tak terbatas: 1.#INF
NaN Tenang: 1.#QNAN
NaN Sinyal: 1.#SNAN
NaN tak terbatas: 1.#IND
Salah satu format ini mungkin telah diawali oleh tanda dan mungkin telah diformat sedikit berbeda tergantung pada lebar bidang dan presisi (kadang-kadang dengan efek yang tidak biasa, misalnya
printf("%.2f\n", INFINITY)
akan mencetak 1,#J karena #INF akan "dibulatkan" ke presisi 2 digit). C99 memperkenalkan persyaratan baru tentang bagaimana infinities dan NaN akan diformat. Implementasi MSVC sekarang sesuai dengan persyaratan ini. String baru adalah sebagai berikut:Tak terbatas: inf
NaN tenang: nan
NaN Sinyal: nan(snan)
NaN Tak Terbatas: nan(ind)
Salah satu dari ini dapat diawali dengan tanda. Jika penentu format kapital digunakan (%F alih-alih %f), maka string dicetak dalam huruf kapital (
INF
bukaninf
), seperti yang diperlukan.Fungsi pemindaian telah dimodifikasi untuk mengurai string baru ini, sehingga string ini sekarang melakukan
printf
perjalanan pulang pergi danscanf
.Pemformatan dan penguraian titik mengambang
Pemformatan titik mengambang baru dan algoritma penguraian telah diperkenalkan untuk meningkatkan kebenaran. Perubahan ini memengaruhi keluarga fungsi cetak dan pemindaian , dan fungsi seperti strtod.
Algoritma pemformatan lama hanya akan menghasilkan sejumlah digit terbatas, kemudian akan mengisi tempat desimal yang tersisa dengan nol. Mereka biasanya dapat menghasilkan string yang akan pulang-pergi kembali ke nilai titik mengambang asli, tetapi tidak bagus jika Anda menginginkan nilai yang tepat (atau representasi desimal terdekat darinya). Algoritma pemformatan baru menghasilkan digit sebanyak yang diperlukan untuk mewakili nilai (atau untuk mengisi presisi yang ditentukan). Sebagai contoh peningkatan; pertimbangkan hasilnya saat mencetak kekuatan besar dua:
printf("%.0f\n", pow(2.0, 80))
Output lama:
1208925819614629200000000
Output baru:
1208925819614629174706176
Algoritma penguraian lama hanya akan mempertimbangkan hingga 17 digit signifikan dari string input dan akan membuang digit lainnya. Pendekatan ini cukup untuk menghasilkan perkiraan dekat dari nilai yang diwakili oleh string, dan hasilnya biasanya sangat dekat dengan hasil yang dibulatkan dengan benar. Implementasi baru mempertimbangkan semua digit yang ada dan menghasilkan hasil yang dibulatkan dengan benar untuk semua input (panjangnya hingga 768 digit). Selain itu, fungsi-fungsi ini sekarang menghormati mode pembulatan (dapat dikontrol melalui fesetround). Ini berpotensi menjadi perubahan perilaku yang melanggar karena fungsi-fungsi ini mungkin menghasilkan hasil yang berbeda. Hasil baru selalu lebih benar daripada hasil lama.
Penguraian titik float heksadesimal dan tak terbatas/NaN
Algoritma penguraian titik mengambang sekarang akan mengurai string titik mengambang heksadesimal (seperti yang dihasilkan oleh penentu format cetak %a dan %A) dan semua string tak terbatas dan NaN yang dihasilkan oleh
printf
fungsi, seperti yang dijelaskan di atas.%A dan %a zero padding
Penentu format %a dan %A memformat angka titik mengambang sebagai mantissa heksadesimal dan eksponen biner. Dalam versi sebelumnya,
printf
fungsi akan salah untai (karakter) zero-pad. Misalnya,printf("%07.0a\n", 1.0)
akan mencetak 00x1p+0, di mana harus mencetak 0x01p+0. Kelemahan ini telah diperbaiki.%A dan %a presisi
Presisi default dari %A dan %a penentu format adalah 6 di versi pustaka sebelumnya. Presisi default sekarang adalah 13 untuk kesamaan dengan Standar C.
Ini adalah perubahan perilaku runtime dalam output fungsi apa pun yang menggunakan string format dengan %A atau %a. Dalam perilaku lama, output yang menggunakan penentu %A mungkin adalah "1.1A2B3Cp+111". Sekarang output untuk nilai yang sama adalah "1.1A2B3C4D5E6F7p+111". Untuk mendapatkan perilaku lama, Anda dapat menentukan presisi, misalnya, %.6A. Lihat Spesifikasi Presisi.
%F penentu
Penentu %F format/konversi sekarang didukung. Ini secara fungsional setara dengan penentu format %f, kecuali bahwa infinities dan NaN diformat menggunakan huruf kapital.
Pada versi sebelumnya, implementasi yang digunakan untuk mengurai F dan N sebagai pengubah panjang. Perilaku ini bertanggal kembali ke usia ruang alamat tersegmentasi: pengubah panjang ini digunakan untuk menunjukkan penunjuk yang jauh dan dekat, masing-masing, seperti dalam %Fp atau %Ns. Perilaku ini telah dihapus. Jika %F ditemukan, sekarang diperlakukan sebagai penentu format %F; jika %N ditemui, sekarang diperlakukan sebagai parameter yang tidak valid.
Pemformatan eksponen
Penentu format %e dan %E memformat angka titik mengambang sebagai mantissa desimal dan eksponen. Penentu format %g dan %G juga memformat angka dalam formulir ini dalam beberapa kasus. Di versi sebelumnya, CRT akan selalu menghasilkan string dengan eksponen tiga digit. Misalnya,
printf("%e\n", 1.0)
akan mencetak 1.000000e+000, yang salah. C mengharuskan jika eksponen dapat diwakili hanya menggunakan satu atau dua digit, maka hanya dua digit yang akan dicetak.Di Visual Studio 2005, sakelar kesuaian global ditambahkan: _set_output_format. Program dapat memanggil fungsi ini dengan argumen _TWO_DIGIT_EXPONENT, untuk mengaktifkan pencetakan eksponen yang sesuai. Perilaku default telah diubah ke mode pencetakan eksponen yang sesuai standar.
Validasi string format
Dalam versi sebelumnya,
printf
fungsi danscanf
akan secara diam-diam menerima banyak string format yang tidak valid, kadang-kadang dengan efek yang tidak biasa. Misalnya, %hlhlhld akan diperlakukan sebagai %d. Semua string format yang tidak valid sekarang diperlakukan sebagai parameter yang tidak valid.validasi string mode fopen
Dalam versi sebelumnya,
fopen
keluarga fungsi secara diam-diam menerima beberapa string mode yang tidak valid, sepertir+b+
. String mode tidak valid sekarang terdeteksi dan diperlakukan sebagai parameter yang tidak valid.mode _O_U8TEXT
Fungsi _setmode sekarang melaporkan mode untuk streaming yang dibuka dengan benar in_O_U8TEXT mode. Di versi pustaka sebelumnya, pustaka akan melaporkan aliran seperti yang dibuka di _O_WTEXT.
Ini adalah perubahan yang melanggar jika kode Anda menginterpretasikan mode _O_WTEXT untuk streaming di mana pengodean adalah UTF-8. Jika aplikasi Anda tidak mendukung UTF_8, pertimbangkan untuk menambahkan dukungan untuk pengodean yang semakin umum ini.
snprintf dan vsnprintf
Fungsi snprintf dan vsnprintf sekarang diimplementasikan. Kode lama sering memberikan definisi versi makro dari fungsi-fungsi ini karena tidak diimplementasikan oleh pustaka CRT, tetapi tidak lagi diperlukan dalam versi yang lebih baru. Jika snprintf atau vsnprintf didefinisikan sebagai makro sebelum menyertakan
<stdio.h>
, kompilasi sekarang gagal dengan kesalahan yang menunjukkan di mana makro ditentukan.Biasanya, perbaikan untuk masalah ini adalah menghapus deklarasi
snprintf
atauvsnprintf
dalam kode pengguna.tmpnam Menghasilkan Nama File yang Dapat Digunakan
Dalam versi sebelumnya,
tmpnam
fungsi dantmpnam_s
menghasilkan nama file di akar drive (seperti \sd3c.). Fungsi-fungsi ini sekarang menghasilkan jalur nama file yang dapat digunakan dalam direktori sementara.Enkapsulasi FILE
Dalam versi sebelumnya, jenis FILE lengkap didefinisikan secara publik di
<stdio.h>
, sehingga dimungkinkan bagi kode pengguna untuk menjangkau file dan memodifikasi internalnya. Pustaka telah diubah untuk menyembunyikan detail implementasi. Sebagai bagian dari perubahan ini, FILE seperti yang didefinisikan sekarang<stdio.h>
adalah jenis buram dan anggotanya tidak dapat diakses dari luar CRT itu sendiri._outp dan _inp
Fungsi _outp, _outpw, _outpd, _inp, _inpw, dan _inpd telah dihapus.
<stdlib.h>
, <malloc.h>
, dan <sys/stat.h>
strtof dan wcstof
Fungsi
strtof
danwcstof
gagal diaturerrno
ke ERANGE ketika nilai tidak dapat diwakili sebagai float. Kesalahan ini khusus untuk kedua fungsi ini;strtod
fungsi ,wcstod
,strtold
, danwcstold
tidak terpengaruh. Masalah ini telah diperbaiki, dan merupakan perubahan yang melanggar runtime.Fungsi alokasi yang diratakan
Dalam versi sebelumnya, fungsi alokasi yang selaras (
_aligned_malloc
, ,_aligned_offset_malloc
dll.) akan secara diam-diam menerima permintaan untuk blok dengan penyelarasan 0. Perataan yang diminta harus berupa kekuatan dua, yang tidak benar dari nol. Penyelarasan 0 yang diminta sekarang diperlakukan sebagai parameter yang tidak valid. Masalah ini telah diperbaiki, dan merupakan perubahan yang melanggar runtime.Fungsi timbunan
Fungsi
_heapadd
,_heapset
, dan_heapused
telah dihapus. Fungsi-fungsi ini tidak berfungsi sejak CRT diperbarui untuk menggunakan tumpukan Windows.smallheap
Opsi
smallheap
tautan telah dihapus. Lihat Opsi Tautan._Stat
Keluarga
_stat
fungsi digunakanCreateFile
di Visual Studio 2015, alih-alihFindFirstFile
seperti di Visual Studio 2013 dan yang lebih lama. Ini berarti bahwa pada jalur yang_stat
diakhir dengan garis miring berhasil jika jalur mengacu pada direktori, dibandingkan dengan sebelumnya ketika fungsi akan kesalahan denganerrno
diatur keENOENT
.
<string.h>
wcstok
Tanda tangan
wcstok
fungsi telah diubah agar sesuai dengan apa yang diperlukan oleh Standar C. Di versi pustaka sebelumnya, tanda tangan fungsi ini adalah:wchar_t* wcstok(wchar_t*, wchar_t const*)
Ini menggunakan konteks internal per utas untuk melacak status di seluruh panggilan, seperti yang dilakukan untuk
strtok
. Fungsi sekarang memiliki tanda tanganwchar_t* wcstok(wchar_t*, wchar_t const*, wchar_t**)
, dan mengharuskan pemanggil untuk meneruskan konteks sebagai argumen ketiga ke fungsi.Fungsi baru
_wcstok
telah ditambahkan dengan tanda tangan lama untuk memudahkan porting. Saat mengkompilasi kode C++, ada juga kelebihanwcstok
sebaris yang memiliki tanda tangan lama. Kelebihan beban ini dinyatakan tidak digunakan lagi. Dalam kode C, Anda dapat define_CRT_NON_CONFORMING_WCSTOK menyebabkan_wcstok
digunakan sebagai penggantiwcstok
.
<time.h>
jam
Di versi sebelumnya,
clock
fungsi diimplementasikan menggunakan Windows APIGetSystemTimeAsFileTime
. Dengan implementasi ini, fungsi jam sensitif terhadap waktu sistem, dan dengan demikian tidak selalu monoton. Fungsi jam telah diisi ulang dalam halQueryPerformanceCounter
dan sekarang monoton.fstat dan _utime
Dalam versi sebelumnya,
_stat
fungsi , ,fstat
dan_utime
salah menangani waktu penghematan siang hari. Sebelum Visual Studio 2013, semua fungsi ini salah menyesuaikan waktu standar seolah-olah mereka berada di siang hari.Di Visual Studio 2013, masalah diperbaiki dalam
_stat
keluarga fungsi, tetapi masalah serupa dalamfstat
keluarga fungsi dan_utime
tidak diperbaiki. Perbaikan parsial ini menyebabkan masalah karena ketidakkonsistensian antara fungsi. Keluargafstat
fungsi dan_utime
sekarang telah diperbaiki, sehingga semua fungsi ini sekarang menangani waktu penghematan siang hari dengan benar dan konsisten.asktime
Dalam versi sebelumnya, fungsi akan mengalihkan
asctime
satu digit hari dengan nol di depannya, misalnya:Fri Jun 06 08:00:00 2014
. Spesifikasi mengharuskan hari-hari seperti itu di-padding dengan ruang depan, seperti dalamFri Jun 6 08:00:00 2014
. Masalah ini telah diperbaiki.strftime dan wcsftime
Fungsi
strftime
danwcsftime
sekarang mendukung penentu format %C, %D, %e, %F, %g, %G, %h, %n, %r, %R, %t, %T, %u, dan %V. Selain itu, pengubah E dan O diurai tetapi diabaikan.Penentu format %c ditentukan sebagai menghasilkan "representasi tanggal dan waktu yang sesuai" untuk lokal saat ini. Dalam lokal C, representasi ini harus sama dengan
%a %b %e %T %Y
, bentuk yang sama seperti yang diproduksi olehasctime
. Dalam versi sebelumnya, penentu format %c waktu yang salah diformat menggunakanMM/DD/YY HH:MM:SS
representasi. Masalah ini telah diperbaiki.timespec dan TIME_UTC
Header
<time.h>
sekarang menentukantimespec
jenis dantimespec_get
fungsi dari Standar C11. Selain itu, makro TIME_UTC, untuk digunakan dengantimespec_get
fungsi, sekarang ditentukan. Pembaruan ini adalah perubahan yang melanggar untuk kode yang memiliki definisi yang bertentangan untuk salah satu pengidentifikasi ini.CLOCKS_PER_SEC
Makro CLOCKS_PER_SEC sekarang meluas ke bilangan bulat jenis
clock_t
, seperti yang diperlukan oleh bahasa C.
Pustaka Standar C++
Untuk mengaktifkan pengoptimalan baru dan pemeriksaan penelusuran kesalahan, implementasi Visual Studio dari Pustaka Standar C++ sengaja memutuskan kompatibilitas biner dari satu versi ke versi berikutnya. Oleh karena itu, ketika Pustaka Standar C++ digunakan, file objek dan pustaka statis yang dikompilasi dengan menggunakan versi yang berbeda tidak dapat dicampur dalam satu biner (EXE atau DLL), dan objek Pustaka Standar C++ tidak dapat diteruskan di antara biner yang dikompilasi dengan menggunakan versi yang berbeda. Pencampuran tersebut memancarkan kesalahan linker tentang ketidakcocokan _MSC_VER. (_MSC_VER adalah makro yang berisi versi utama pengkompilasi—misalnya, 1800 untuk Visual Studio 2013.) Pemeriksaan ini tidak dapat mendeteksi pencampuran DLL, dan tidak dapat mendeteksi pencampuran yang melibatkan Visual Studio 2008 atau yang lebih lama.
Pustaka Standar C++ menyertakan file
Beberapa perubahan telah dilakukan pada struktur include di header Pustaka Standar C++. Header Pustaka Standar C++ diizinkan untuk menyertakan satu sama lain dengan cara yang tidak ditentukan. Secara umum, Anda harus menulis kode Anda sehingga dengan hati-hati menyertakan semua header yang dibutuhkan sesuai dengan standar C++, dan tidak bergantung pada header Pustaka Standar C++ mana yang menyertakan header Pustaka Standar C++ lainnya. Ini membuat kode portabel di seluruh versi dan platform. Setidaknya dua perubahan header di Visual Studio 2015 memengaruhi kode pengguna. Pertama,
<string>
tidak lagi termasuk<iterator>
. Kedua,<tuple>
sekarang menyatakanstd::array
tanpa menyertakan semua<array>
, yang dapat memecahkan kode melalui kombinasi konstruksi kode berikut: kode Anda memiliki variabel bernama "array", dan Anda memiliki direktif penggunaan "menggunakan namespace std;", dan Anda menyertakan header Pustaka Standar C++ (seperti<functional>
) yang mencakup<tuple>
, yang sekarang menyatakanstd::array
.steady_clock
Implementasi
<chrono>
steady_clock
telah berubah untuk memenuhi persyaratan Standar C++ untuk ketepatan dan monotonisitas.steady_clock
sekarang didasarkan padaQueryPerformanceCounter
danhigh_resolution_clock
sekarang menjadi typedef untuksteady_clock
. Akibatnya, di Visual Studiosteady_clock::time_point
sekarang menjadi typedef untukchrono::time_point<steady_clock>
; namun, ini belum tentu terjadi untuk implementasi lain.alokator dan const
Kami sekarang memerlukan perbandingan kesetaraan/ketidaksetaraan alokator untuk menerima argumen const di kedua sisi. Jika alokator Anda menentukan operator ini seperti ini,
bool operator==(const MyAlloc& other)
maka Anda harus memperbaruinya dan menyatakannya sebagai anggota const:
bool operator==(const MyAlloc& other) const
elemen const
Standar C++ selalu melarang kontainer elemen const (seperti
vector<const T>
atauset<const T>
). Visual Studio 2013 dan sebelumnya menerima kontainer tersebut. Dalam versi saat ini, kontainer tersebut gagal dikompilasi.std::allocator::d eallocate
Di Visual Studio 2013 dan yang lebih lama,
std::allocator::deallocate(p, n)
abaikan argumen yang diteruskan untuk n. Standar C++ selalu mengharuskan n harus sama dengan nilai yang diteruskan sebagai argumen pertama untuk pemanggilanallocate
, yang mengembalikan p. Namun, dalam versi saat ini, nilai n diperiksa. Kode yang meneruskan argumen untuk n yang berbeda dari apa yang diperlukan standar mungkin crash saat runtime.hash_map dan hash_set
File
<hash_map>
header non-standar dan<hash_set>
tidak digunakan lagi di Visual Studio 2015 dan akan dihapus dalam rilis mendatang. Gunakan<unordered_map>
dan<unordered_set>
sebagai gantinya.komparator dan operator()
Kontainer asosiatif (
<map>
keluarga) sekarang mengharuskan komparator mereka untuk memiliki operator panggilan fungsi yang dapat dipanggil secara const. Kode berikut dalam deklarasi kelas komparator sekarang gagal dikompilasi:bool operator()(const X& a, const X& b)
Untuk mengatasi kesalahan ini, ubah deklarasi fungsi menjadi:
bool operator()(const X& a, const X& b) const
jenis sifat
Nama lama untuk sifat jenis dari versi standar draf C++ yang lebih lama telah dihapus. Ini diubah di C++11 dan telah diperbarui ke nilai C++11 di Visual Studio 2015. Tabel berikut ini memperlihatkan nama lama dan baru.
Nama lama Nama baru 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 dan launch::sync policies
Kebijakan dan
launch::sync
nonstandardlaunch::any
dihapus. Sebagai gantinya, untuklaunch::any
, gunakanlaunch:async | launch:deferred
. Untuklaunch::sync
, gunakanlaunch::deferred
. Lihat meluncurkan Enumerasi.
MFC dan ATL
Kelas Microsoft Foundation (MFC)
tidak lagi disertakan dalam penginstalan Visual Studio "Khas" karena ukurannya yang besar. Untuk menginstal MFC, pilih opsi Penginstalan kustom di penyiapan Visual Studio 2015. Jika Anda sudah menginstal Visual Studio 2015, Anda dapat menginstal MFC dengan menjalankan penyiapan Visual Studio lagi. Pilih opsi Instal kustom, lalu pilih Kelas Microsoft Foundation. Anda dapat menjalankan penyiapan Visual Studio dari Panel Kontrol mengontrol Program dan Fitur, atau dari media penginstalan.
Paket Visual C++ Redistributable masih menyertakan pustaka ini.
Runtime Konkurensi
Menghasilkan makro dari Windows.h yang bertentangan dengan konkurensi::Context::Yield
Runtime Konkurensi yang sebelumnya digunakan
#undef
untuk tidak menentukan makro Hasil untuk menghindari konflik antara makro Yield yang ditentukan dalam Windows.h h danconcurrency::Context::Yield
fungsi . Ini#undef
telah dihapus dan konkurensi panggilan API setara yang tidak bertentangan baru::Context::YieldExecution telah ditambahkan. Untuk mengatasi konflik dengan Yield, Anda dapat memperbarui kode untuk memanggilYieldExecution
fungsi sebagai gantinya, atau mengelilingiYield
nama fungsi dengan tanda kurung di situs panggilan, seperti dalam contoh berikut:(concurrency::Context::Yield)();
Peningkatan Kesuaian Kompilator di Visual Studio 2015
Saat meningkatkan kode dari versi sebelumnya, Anda mungkin juga mengalami kesalahan kompilator yang disebabkan oleh peningkatan kesuaian yang dilakukan di Visual Studio 2015. Peningkatan ini tidak merusak kompatibilitas biner dari versi Visual Studio sebelumnya, tetapi dapat menghasilkan kesalahan pengkompilasi di mana tidak ada yang dipancarkan sebelumnya. Untuk informasi selengkapnya, lihat Visual C++ Apa yang Baru 2003 hingga 2015.
Di Visual Studio 2015, peningkatan berkelanjutan pada kesuaian kompilator terkadang dapat mengubah cara pengkompilasi memahami kode sumber yang ada. Akibatnya, Anda mungkin mengalami kesalahan baru atau berbeda selama build Anda, atau bahkan perbedaan perilaku dalam kode yang sebelumnya dibangun dan tampaknya berjalan dengan benar.
Untungnya, perbedaan ini memiliki sedikit atau tidak berdampak pada sebagian besar kode sumber Anda. Ketika kode sumber atau perubahan lain diperlukan untuk mengatasi perbedaan ini, perbaikan cenderung kecil dan lurus ke depan. Kami telah menyertakan banyak contoh kode sumber yang dapat diterima sebelumnya yang mungkin perlu diubah (sebelumnya) dan perbaikan untuk memperbaikinya (setelah).
Meskipun perbedaan ini dapat memengaruhi kode sumber Anda atau artefak build lainnya, perbedaan tersebut tidak memengaruhi kompatibilitas biner antara pembaruan ke versi Visual Studio. Perubahan yang melanggar lebih parah, dan dapat memengaruhi kompatibilitas biner, tetapi jenis pemutusan kompatibilitas biner ini hanya terjadi antara versi utama Visual Studio, misalnya, antara Visual Studio 2013 dan Visual Studio 2015. Untuk informasi tentang perubahan mencolok yang terjadi antara Visual Studio 2013 dan Visual Studio 2015, lihat Perubahan Kesamaan Visual Studio 2015.
Peningkatan Kesuaian di Visual Studio 2015
Opsi /Zc:forScope-
Opsi
/Zc:forScope-
kompilator tidak digunakan lagi dan akan dihapus dalam rilis mendatang.Command line warning D9035: option 'Zc:forScope-' has been deprecated and will be removed in a future release
Biasanya, opsi ini digunakan untuk memungkinkan kode non-standar yang menggunakan variabel perulangan setelah titik di mana, sesuai dengan standar, mereka harus keluar dari cakupan. Itu hanya diperlukan ketika Anda mengkompilasi dengan
/Za
opsi, karena tanpa/Za
, penggunaan variabel untuk perulangan setelah akhir perulangan selalu diizinkan. Jika Anda tidak peduli tentang kesuaian standar (misalnya, jika kode Anda tidak dimaksudkan untuk portabel ke pengkompilasi lain), Anda dapat menonaktifkan/Za
opsi (atau mengatur properti Nonaktifkan Ekstensi Bahasa ke Tidak). Jika Anda peduli tentang menulis kode portabel dan sesuai standar, Anda harus menulis ulang kode Anda sehingga sesuai dengan standar dengan memindahkan deklarasi variabel tersebut ke titik di luar perulangan.// 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
opsi pengkompilasiOpsi
/Zg
pengkompilasi (Hasilkan Prototipe Fungsi) tidak lagi tersedia. Opsi kompilator ini sebelumnya tidak digunakan lagi.Anda tidak dapat lagi menjalankan pengujian unit dengan C++/CLI dari baris perintah dengan mstest.exe. Sebagai gantinya, gunakan vstest.console.exe. Lihat VSTest.Console.exe opsi baris perintah.
kata kunci yang dapat diubah
Penentu
mutable
kelas penyimpanan tidak lagi diizinkan di tempat-tempat di mana sebelumnya dikompilasi tanpa kesalahan. Sekarang, kompilator memberikan kesalahan C2071 (kelas penyimpanan ilegal). Menurut standar, penentumutable
hanya dapat diterapkan ke nama anggota data kelas, dan tidak dapat diterapkan ke nama yang dinyatakan const atau statis, dan tidak dapat diterapkan ke anggota referensi.Sebagai contoh, perhatikan kode berikut:
struct S { mutable int &r; };
Versi kompilator sebelumnya menerima ini, tetapi sekarang pengkompilasi memberikan kesalahan berikut:
error C2071: 'S::r': illegal storage class
Untuk memperbaiki kesalahan, hapus kata kunci redundan
mutable
.char_16_t dan char32_t
Anda tidak dapat lagi menggunakan
char16_t
atauchar32_t
sebagai alias dalamtypedef
, karena jenis ini sekarang diperlakukan sebagai bawaan. Pengguna dan penulis pustaka umum untuk mendefinisikanchar16_t
danchar32_t
sebagai alias danuint16_t
uint32_t
, masing-masing.#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; }
Untuk memperbarui kode Anda, hapus
typedef
deklarasi dan ganti nama pengidentifikasi lain yang bertabrakan dengan nama-nama ini.Parameter templat non-jenis
Kode tertentu yang melibatkan parameter templat non-jenis sekarang diperiksa dengan benar untuk kompatibilitas jenis saat Anda memberikan argumen templat eksplisit. Misalnya, kode berikut dikompilasi tanpa kesalahan di versi Visual Studio sebelumnya.
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>(); }
Pengkompilasi saat ini memberikan kesalahan dengan benar, karena jenis parameter templat tidak cocok dengan argumen templat (parameter adalah penunjuk ke anggota const, tetapi fungsi f non-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'
Untuk mengatasi kesalahan ini dalam kode Anda, pastikan bahwa jenis argumen templat yang Anda gunakan cocok dengan jenis parameter templat yang dideklarasikan.
__declspec(align)
Pengkompilasi tidak lagi menerima
__declspec(align)
fungsi. Konstruksi ini selalu diabaikan, tetapi sekarang menghasilkan kesalahan kompilator.error C3323: 'alignas' and '__declspec(align)' are not allowed on function declarations
Untuk memperbaiki masalah ini, hapus
__declspec(align)
dari deklarasi fungsi. Karena tidak berpengaruh, menghapusnya tidak mengubah apa pun.Penanganan pengecualian
Ada beberapa perubahan pada penanganan pengecualian. Pertama, objek pengecualian harus dapat disalin atau bergerak. Kode berikut dikompilasi di Visual Studio 2013, tetapi tidak dikompilasi di Visual Studio 2015:
struct S { public: S(); private: S(const S &); }; int main() { throw S(); // error }
Masalahnya adalah bahwa konstruktor salinan bersifat pribadi, sehingga objek tidak dapat disalin seperti yang terjadi dalam perjalanan normal menangani pengecualian. Hal yang sama berlaku ketika konstruktor salinan dinyatakan
explicit
.struct S { S(); explicit S(const S &); }; int main() { throw S(); // error }
Untuk memperbarui kode Anda, pastikan bahwa konstruktor salinan untuk objek pengecualian Anda adalah
public
dan tidak ditandaiexplicit
.Menangkap pengecualian berdasarkan nilai juga mengharuskan objek pengecualian dapat disalin. Kode berikut dikompilasi di Visual Studio 2013, tetapi tidak dikompilasi di Visual Studio 2015:
struct B { public: B(); private: B(const B &); }; struct D : public B {}; int main() { try { } catch (D d) // error { } }
Anda dapat memperbaiki masalah ini dengan mengubah jenis parameter untuk
catch
menjadi referensi.catch (D& d) { }
String literal diikuti oleh makro
Kompiler sekarang mendukung literal yang ditentukan pengguna. Sebagai konsekuensinya, string harfiah diikuti oleh makro tanpa spasi yang mengintervensi ditafsirkan sebagai literal yang ditentukan pengguna, yang mungkin menghasilkan kesalahan atau hasil yang tidak terduga. Misalnya, di kompilator sebelumnya, kode berikut berhasil dikompilasi:
#define _x "there" char* func() { return "hello"_x; } int main() { char * p = func(); return 0; }
Kompiler menafsirkan kode ini sebagai string harfiah "hello" diikuti oleh makro, yang diperluas ke "sana", dan kemudian dua literal string digabungkan menjadi satu. Di Visual Studio 2015, pengkompilasi menafsirkan urutan ini sebagai harfiah yang ditentukan pengguna, tetapi karena tidak ada yang cocok yang ditentukan pengguna secara harfiah
_x
, itu memberikan kesalahan.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?
Untuk memperbaiki masalah ini, tambahkan spasi antara string literal dan makro.
Literal string yang berdekatan
Demikian pula dengan sebelumnya, karena perubahan terkait dalam penguraian string, literal string yang berdekatan (baik literal string karakter lebar atau sempit) tanpa spasi putih ditafsirkan sebagai string tunggal yang digabungkan dalam rilis Visaul C++sebelumnya. Di Visual Studio 2015, Anda sekarang harus menambahkan spasi kosong di antara dua string. Misalnya, kode berikut harus diubah:
char * str = "abc""def";
Untuk memperbaiki masalah ini, tambahkan spasi di antara dua string:
char * str = "abc" "def";
Penempatan baru dan hapus
Perubahan telah dilakukan pada
delete
operator agar sesuai dengan standar C++14. Detail perubahan standar dapat ditemukan di Alokasi Berukuran C++. Perubahan menambahkan bentuk operator globaldelete
yang mengambil parameter ukuran. Perubahan yang melanggar adalah bahwa jika Sebelumnya Anda menggunakan operatordelete
dengan tanda tangan yang sama (sesuai dengan operator baru penempatan), Anda akan menerima kesalahan kompilator (C2956, yang terjadi pada titik di mana penempatan baru digunakan, karena itulah posisi dalam kode di mana pengkompilasi mencoba mengidentifikasi operator pencocokandelete
yang sesuai).Fungsi
void operator delete(void *, size_t)
ini adalah operator penghapusan penempatan yang sesuai dengan fungsivoid * operator new(size_t, size_t)
baru penempatan di C++11. Dengan dealokasi berukuran C++14, fungsi penghapusan ini sekarang merupakan fungsi dealokasi biasa (operator globaldelete
). Standar mengharuskan bahwa jika penggunaan penempatan baru mencari fungsi penghapusan yang sesuai dan menemukan fungsi dealokasi yang biasa, program akan terbentuk dengan tidak benar.Misalnya, kode Anda menentukan penempatan baru dan penghapusan penempatan:
void * operator new(std::size_t, std::size_t); void operator delete(void*, std::size_t) noexcept;
Masalah terjadi karena kecocokan dalam tanda tangan fungsi antara operator penghapusan penempatan yang telah Anda tentukan, dan operator berukuran
delete
global baru. Pertimbangkan apakah Anda dapat menggunakan jenis yang berbeda selainsize_t
untuk penempatan apa pun yang baru dandelete
operator. Jenisnyasize_t
typedef
adalah compiler-dependent; ini adalahtypedef
untukunsigned int
di MSVC. Solusi yang baik adalah menggunakan jenis enumerasi seperti ini:enum class my_type : size_t {};
Kemudian, ubah definisi penempatan Anda baru dan
delete
untuk menggunakan jenis ini sebagai argumen kedua alih-alihsize_t
. Anda juga harus memperbarui panggilan ke penempatan baru untuk meneruskan jenis baru (misalnya, dengan menggunakanstatic_cast<my_type>
untuk mengonversi dari nilai bilangan bulat) dan memperbarui definisi dandelete
untuk mentransmisikan kembali ke jenis bilangannew
bulat. Anda tidak perlu menggunakanenum
untuk ini; jenis kelas dengansize_t
anggota juga akan berfungsi.Solusi alternatifnya adalah Anda mungkin dapat menghilangkan penempatan baru sama sekali. Jika kode Anda menggunakan penempatan baru untuk mengimplementasikan kumpulan memori di mana argumen penempatan adalah ukuran objek yang dialokasikan atau dihapus, maka fitur dealokasi berukuran mungkin cocok untuk mengganti kode kumpulan memori kustom Anda sendiri, dan Anda dapat menyingkirkan fungsi penempatan dan hanya menggunakan operator dua argumen
delete
Anda sendiri alih-alih fungsi penempatan.Jika Anda tidak ingin segera memperbarui kode, Anda dapat kembali ke perilaku lama dengan menggunakan opsi
/Zc:sizedDealloc-
pengkompilasi . Jika Anda menggunakan opsi ini, fungsi penghapusan dua argumen tidak ada dan tidak akan menyebabkan konflik dengan operator penghapusan penempatan Anda.Anggota data union
Anggota data dari serikat tidak dapat lagi memiliki jenis referensi. Kode berikut berhasil dikompilasi di Visual Studio 2013, tetapi menghasilkan kesalahan di Visual Studio 2015.
union U1 { const int i; }; union U2 { int & i; }; union U3 { struct { int & i; }; };
Kode sebelumnya menghasilkan kesalahan berikut:
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
Untuk mengatasi masalah ini, ubah jenis referensi baik ke penunjuk atau nilai. Mengubah jenis menjadi penunjuk memerlukan perubahan dalam kode yang menggunakan bidang union. Mengubah kode menjadi nilai akan mengubah data yang disimpan dalam gabungan, yang memengaruhi bidang lain karena bidang dalam jenis gabungan berbagi memori yang sama. Tergantung pada ukuran nilai, nilai juga dapat mengubah ukuran serikat.
Serikat anonim sekarang lebih sesuai dengan standar. Versi kompilator sebelumnya menghasilkan konstruktor dan destruktor eksplisit untuk serikat anonim. Fungsi yang dihasilkan kompilator ini dihapus di Visual Studio 2015.
struct S { S(); }; union { struct { S s; }; } u; // C2280
Kode sebelumnya menghasilkan kesalahan berikut di 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
Untuk mengatasi masalah ini, berikan definisi Anda sendiri tentang konstruktor dan/atau destruktor.
struct S { // Provide a default constructor by adding an empty function body. S() {} }; union { struct { S s; }; } u;
Serikat dengan struktur anonim
Untuk menyesuaikan dengan standar, perilaku runtime telah berubah untuk anggota struktur anonim dalam serikat. Konstruktor untuk anggota struktur anonim dalam serikat tidak lagi secara implisit dipanggil ketika serikat tersebut dibuat. Selain itu, destruktor untuk anggota struktur anonim dalam serikat tidak lagi secara implisit dipanggil ketika penyatuan keluar dari cakupan. Pertimbangkan kode berikut, di mana union U berisi struktur anonim yang berisi struktur anggota bernama S yang memiliki destruktor.
#include <stdio.h> struct S { S() { printf("Creating S\n"); } ~S() { printf("Destroying S\n"); } }; union U { struct { S s; }; U() {} ~U() {} }; void f() { U u; // Destructor implicitly called here. } int main() { f(); char s[1024]; printf("Press any key.\n"); gets_s(s); return 0; }
Di Visual Studio 2013, konstruktor untuk S dipanggil saat penyatuan dibuat, dan destruktor untuk S dipanggil ketika tumpukan untuk fungsi f dibersihkan. Tetapi di Visual Studio 2015, konstruktor dan destruktor tidak dipanggil. Pengkompilasi memberikan peringatan tentang perubahan perilaku ini.
warning C4587: 'U::s': behavior change: constructor is no longer implicitly calledwarning C4588: 'U::s': behavior change: destructor is no longer implicitly called
Untuk memulihkan perilaku asli, beri nama struktur anonim. Perilaku runtime struktur non-anonim sama, terlepas dari versi pengompilasi.
#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; }
Atau, coba pindahkan kode konstruktor dan destruktor ke fungsi baru, dan tambahkan panggilan ke fungsi-fungsi ini dari konstruktor dan destruktor untuk serikat.
#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; }
Resolusi templat
Perubahan telah dilakukan pada resolusi nama untuk templat. Di C++, ketika mempertimbangkan kandidat untuk resolusi nama, bisa jadi satu atau beberapa nama dipertimbangkan karena potensi kecocokan menghasilkan instansiasi templat yang tidak valid. Instansiasi yang tidak valid ini biasanya tidak menyebabkan kesalahan kompilator, prinsip yang dikenal sebagai SFINAE (Kegagalan Penggantian Bukan Kesalahan).
Sekarang, jika SFINAE mengharuskan pengkompilasi untuk membuat instans spesialisasi templat kelas, maka kesalahan apa pun yang terjadi selama proses ini adalah kesalahan kompilator. Di versi sebelumnya, pengkompilasi akan mengabaikan kesalahan tersebut. Sebagai contoh, perhatikan kode berikut:
#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); }
Jika Anda mengkompilasi dengan pengkompilasi saat ini, Anda mendapatkan kesalahan berikut:
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 ]
Ini karena pada titik pemanggilan pertama is_base_of kelas
D
belum ditentukan.Dalam hal ini, perbaikannya adalah tidak menggunakan sifat jenis tersebut sampai kelas telah ditentukan. Jika Anda memindahkan definisi
B
danD
ke awal file kode, kesalahan akan diatasi. Jika definisi berada dalam file header, periksa urutan pernyataan sertakan untuk file header untuk memastikan bahwa definisi kelas apa pun dikompilasi sebelum templat bermasalah digunakan.Menyalin konstruktor
Di Visual Studio 2013 dan Visual Studio 2015, kompilator menghasilkan konstruktor salinan untuk kelas jika kelas tersebut memiliki konstruktor pemindahan yang ditentukan pengguna tetapi tidak ada konstruktor salinan yang ditentukan pengguna. Di Dev14, konstruktor salinan yang dihasilkan secara implisit ini juga ditandai "= hapus".
utama yang dinyatakan sebagai ekstern "C" sekarang memerlukan jenis pengembalian.
Kode berikut sekarang menghasilkan C4430.
extern "C" __cdecl main(){} // C4430
Untuk memperbaiki kesalahan, tambahkan jenis pengembalian:
extern "C" int __cdecl main(){} // OK
typename tidak diperbolehkan dalam penginisialisasi anggota
Kode berikut sekarang menghasilkan C2059:
template<typename T> struct S1 : public T::type { S1() : typename T::type() // C2059 { } }; struct S2 { typedef S2 type; }; S1<S2> s;
Untuk memperbaiki kesalahan, hapus
typename
dari penginisialisasi:S1() : T::type() // OK ...
Kelas penyimpanan pada spesialisasi eksplisit diabaikan.
Dalam kode berikut, penentu kelas penyimpanan statis diabaikan
template <typename T> void myfunc(T h) { } template<> static void myfunc(double h) // static is ignored { }
Konstanta yang digunakan dalam static_assert di dalam templat kelas akan selalu gagal.
Kode berikut menyebabkan
static_assert
selalu gagal:template <size_t some_value> struct S1 { static_assert(false, "default not valid"); // always invoked }; //other partial specializations here
Untuk mengatasi masalah ini, bungkus nilai dalam
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
Aturan yang diberlakukan untuk deklarasi penerusan. (Hanya berlaku untuk C.)
Kode berikut sekarang menghasilkan C2065:
struct token_s; typedef int BOOL; typedef int INT; typedef int(*PFNTERM)(PTOKEN, BOOL, INT); // C2065: 'PTOKEN' : undeclared identifier
Untuk memperbaiki masalah ini, tambahkan deklarasi penerusan yang tepat:
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);
Penegakan jenis penunjuk fungsi yang lebih konsisten
Kode berikut sekarang menghasilkan C2197:
typedef int(*F1)(int); typedef int(*F2)(int, int); void func(F1 f, int v1, int v2) { f(v1, v2); // C2197 }
Panggilan ambigu ke fungsi yang kelebihan beban
Kode berikut sekarang menghasilkan C266: 'N::bind': panggilan ambigu ke fungsi yang kelebihan beban
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 } };
Untuk memperbaiki kesalahan, Anda dapat sepenuhnya memenuhi syarat panggilan ke
bind: N::bind(...)
. Namun, jika perubahan ini dimanifestasikan melalui pengidentifikasi yang tidak dinyatakan (C2065), maka mungkin tepat untuk memperbaikinya denganusing
deklarasi sebagai gantinya.Pola ini sering terjadi dengan ComPtr dan jenis lain di
Microsoft::WRL
namespace layanan.Perbaiki alamat yang salah dari
Kode berikut sekarang menghasilkan C2440: '=': tidak dapat mengonversi dari 'type *' ke 'type'. Untuk memperbaiki kesalahan, ubah &(ketik) menjadi (type) dan (&f()) menjadi (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()); }
String literal adalah array konstanta
Kode berikut sekarang menghasilkan C2664: 'void f(void )': tidak dapat mengonversi argumen 1 dari 'const char ()[2]' ke 'void *'
void f(void *); void h(void) { f(&__FUNCTION__); void *p = &""; }
Untuk memperbaiki kesalahan, ubah jenis parameter fungsi menjadi
const void*
, atau ubah isih
agar terlihat seperti contoh ini:void h(void) { char name[] = __FUNCTION__; f( name); void *p = &""; }
String UDL C++11
Kode berikut sekarang menghasilkan kesalahan C3688: akhiran harfiah 'L' yang tidak valid; operator literal atau operator literal template 'operator ""L' tidak ditemukan
#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"); }
Untuk memperbaiki kesalahan, ubah kode untuk menambahkan spasi:
#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"); }
Dalam contoh di atas,
MACRO
tidak lagi diurai sebagai dua token (string diikuti oleh makro). Sekarang diurai sebagai UDL token tunggal. Hal yang sama berlaku untuk L""L", yang diurai sebelumnya sebagai L"" dan L"", dan sekarang diurai sebagai L""L dan "".Aturan perangkaian string juga dibawa sesuai dengan standar, yang berarti L"a" "b" setara dengan L"ab". Edisi Visual Studio sebelumnya tidak menerima perangkaian string dengan lebar karakter yang berbeda.
Karakter kosong C++11 dihapus
Kode berikut sekarang menghasilkan kesalahan C2137: konstanta karakter kosong
bool check(wchar_t c){ return c == L''; //implicit null character }
Untuk memperbaiki kesalahan, ubah kode untuk membuat null eksplisit:
bool check(wchar_t c){ return c == L'\0'; }
Pengecualian MFC tidak dapat ditangkap oleh nilai karena tidak dapat disalin
Kode berikut dalam aplikasi MFC sekarang menyebabkan kesalahan C2316: 'D': tidak dapat ditangkap karena konstruktor destruktor dan/atau salinan tidak dapat diakses atau dihapus
struct B { public: B(); private: B(const B &); }; struct D : public B { }; int main() { try { } catch (D) // C2316 { } }
Untuk memperbaiki kode, Anda dapat mengubah blok tangkapan menjadi
catch (const D &)
tetapi solusi yang lebih baik biasanya menggunakan makro MFC TRY/CATCH.alignof
sekarang menjadi kata kunciKode berikut sekarang menghasilkan kesalahan C2332: 'class': nama tag yang hilang. Untuk memperbaiki kode, Anda harus mengganti nama kelas atau, jika kelas melakukan pekerjaan yang sama dengan
alignof
, cukup ganti kelas dengan kata kunci baru.class alignof{}
constexpr
sekarang menjadi kata kunciKode berikut sekarang menghasilkan kesalahan C2059: kesalahan sintaks: ')'. Untuk memperbaiki kode, Anda harus mengganti nama fungsi atau nama variabel apa pun yang disebut
constexpr
.int constexpr() {return 1;}
Jenis movable tidak dapat menjadi const
Ketika fungsi mengembalikan jenis yang dimaksudkan untuk dipindahkan, jenis pengembaliannya tidak boleh
const
.Konstruktor salinan yang dihapus
Kode berikut sekarang menghasilkan C2280 'S::S(S &)': mencoba mereferensikan fungsi yang dihapus:
struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = S(2, 3); //C2280
Untuk memperbaiki kesalahan, gunakan inisialisasi langsung untuk
S2
:struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = {2,3}; //OK
Konversi ke penunjuk fungsi hanya dihasilkan ketika tidak ada pengambilan lambda
Kode berikut menghasilkan C2664 di Visual Studio 2015.
void func(int(*)(int)) {} int main() { func([=](int val) { return val; }); }
Untuk memperbaiki kesalahan, hapus
=
dari daftar pengambilan.Panggilan ambigu yang melibatkan operator konversi
Kode berikut sekarang menghasilkan kesalahan C2440: 'type cast': tidak dapat mengonversi dari 'S2' ke 'S1':
struct S1 { S1(int); }; struct S2 { operator S1(); operator int(); }; void f(S2 s2) { (S1)s2; }
Untuk memperbaiki kesalahan, panggil operator konversi secara eksplisit:
void f(S2 s2) { //Explicitly call the conversion operator s2.operator S1(); // Or S1((int)s2); }
Kode berikut sekarang menghasilkan kesalahan C2593: 'operator =' ambigu:
struct S1 {}; struct S2 { operator S1&(); operator S1() const; }; void f(S1 *p, S2 s) { *p = s; }
Untuk memperbaiki kesalahan, panggil operator konversi secara eksplisit:
void f(S1 *p, S2 s) { *p = s.operator S1&(); }
Memperbaiki inisialisasi salinan yang tidak valid dalam inisialisasi anggota data non-statis (NSDMI)
Kode berikut sekarang menghasilkan kesalahan C2664: 'S1::S1(S1 &&)': tidak dapat mengonversi argumen 1 dari 'bool' ke 'const S1 &':
struct S1 { explicit S1(bool); }; struct S2 { S1 s2 = true; // error };
Untuk memperbaiki kesalahan, gunakan inisialisasi langsung:
struct S2 { S1 s1{true}; // OK };
Mengakses konstruktor di dalam pernyataan decltype
Kode berikut sekarang menghasilkan C2248: 'S::S': tidak dapat mengakses anggota privat yang dideklarasikan di kelas 'S':
class S { S(); public: int i; }; class S2 { auto f() -> decltype(S().i); };
Untuk memperbaiki kesalahan, tambahkan deklarasi teman untuk
S2
diS
:class S { S(); friend class S2; // Make S2 a friend public: int i; };
Ctor default lambda dihapus secara implisit
Kode berikut sekarang menghasilkan kesalahan C3497: Anda tidak dapat membuat instans lambda:
void func(){ auto lambda = [](){}; decltype(lambda) other; }
Untuk memperbaiki kesalahan, hapus kebutuhan konstruktor default untuk dipanggil. Jika lambda tidak menangkap apa pun, maka lambda dapat dilemparkan ke penunjuk fungsi.
Lambdas dengan operator penugasan yang dihapus
Kode berikut sekarang menghasilkan kesalahan 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); }
Untuk memperbaiki kesalahan, ganti lambda dengan kelas functor atau hapus kebutuhan untuk menggunakan operator penugasan.
Mencoba memindahkan objek dengan konstruktor salinan yang dihapus
Kode berikut sekarang menghasilkan kesalahan C2280: 'moveable::moveable(const moveable &)': mencoba mereferensikan fungsi yang dihapus
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; };
Untuk memperbaiki kesalahan, gunakan
std::move
sebagai gantinya:S(moveable && m) : m_m(std::move(m))
Kelas lokal tidak dapat mereferensikan kelas lokal lain yang ditentukan nanti dalam fungsi yang sama
Kode berikut sekarang menghasilkan kesalahan C2079: 's' menggunakan struct 'main::S2' yang tidak ditentukan
int main() { struct S2; struct S1 { void f() { S2 s; } }; struct S2 {}; }
Untuk memperbaiki kesalahan, pindah ke atas definisi
S2
:int main() { struct S2 { //moved up }; struct S1 { void f() { S2 s; } }; }
Tidak dapat memanggil ctor dasar yang dilindungi dalam isi ctor turunan.
Kode berikut sekarang menghasilkan kesalahan C2248: 'S1::S1': tidak dapat mengakses anggota yang dilindungi yang dideklarasikan di kelas 'S1'
struct S1 { protected: S1(); }; struct S2 : public S1 { S2() { S1(); } };
Untuk memperbaiki kesalahan, hapus
S2
panggilan keS1()
dari konstruktor dan jika perlu letakkan di fungsi lain.{} mencegah konversi ke penunjuk
Kode berikut sekarang menghasilkan C2439 'S::p': anggota tidak dapat diinisialisasi
struct S { S() : p({ 0 }) {} void *p; };
Untuk memperbaiki kesalahan, hapus kurung kurawal dari sekitar
0
atau gunakannullptr
sebagai gantinya, seperti yang ditunjukkan dalam contoh ini:struct S { S() : p(nullptr) {} void *p; };
Definisi makro dan penggunaan yang salah dengan tanda kurung
Contoh berikut sekarang menghasilkan kesalahan C2008: ';': tidak terduga dalam definisi makro
#define A; //cause of error struct S { A(); // error };
Untuk memperbaiki masalah, ubah baris atas menjadi
#define A();
Kode berikut menghasilkan kesalahan C2059: kesalahan sintaks: ')'
//notice the space after 'A' #define A () ; struct S { A(); };
Untuk memperbaiki kode, hapus spasi antara A dan ().
Kode berikut menghasilkan kesalahan C2091: fungsi mengembalikan fungsi:
#define DECLARE void f() struct S { DECLARE(); };
Untuk memperbaiki kesalahan, hapus tanda kurung setelah DECLARE di S:
DECLARE;
.Kode berikut menghasilkan kesalahan C2062: ketik 'int' tidak terduga
#define A (int) struct S { A a; };
Untuk memperbaiki masalah, tentukan
A
seperti ini:#define A int
Paren tambahan dalam deklarasi
Kode berikut menghasilkan kesalahan C2062: ketik 'int' tidak terduga
struct S { int i; (int)j; };
Untuk memperbaiki kesalahan, hapus tanda kurung di sekitar
j
. Jika tanda kurung diperlukan untuk kejelasan, maka gunakantypedef
.Konstruktor dan __declspec yang dihasilkan kompilator (dapat dihidupkan)
Di Visual Studio 2015, ada peningkatan kemungkinan bahwa konstruktor inline yang dihasilkan kompilator kelas abstrak dengan kelas dasar virtual dapat mengekspos penggunaan
__declspec(novtable)
yang tidak tepat ketika digunakan dalam kombinasi dengan__declspec(dllimport)
.otomatis memerlukan ekspresi tunggal dalam direct-list-initialization
Kode berikut sekarang menghasilkan kesalahan C3518: 'testPositions': dalam konteks direct-list-initialization jenis untuk 'auto' hanya dapat disimpulkan dari ekspresi penginisialisasi tunggal
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} };
Untuk memperbaiki kesalahan, salah satu kemungkinannya adalah menginisialisasi
testPositions
sebagai berikut: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} };
Memeriksa jenis vs. pointer ke jenis untuk is_convertible
Kode berikut sekarang menyebabkan pernyataan statis gagal.
struct B1 { private: B1(const B1 &); }; struct B2 : public B1 {}; struct D : public B2 {}; static_assert(std::is_convertible<D, B2>::value, "fail");
Untuk memperbaiki kesalahan, ubah
static_assert
sehingga membandingkan pointer denganD
danB2
:static_assert(std::is_convertible<D*, B2*>::value, "fail");
deklarasi __declspec(dapat diubah) harus konsisten
__declspec
deklarasi harus konsisten di semua pustaka. Kode berikut sekarang akan menghasilkan pelanggaran aturan satu definisi (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;
Penyempurnaan Kesuaian di Pembaruan 1
Kelas dasar virtual privat dan pewarisan tidak langsung
Versi kompilator sebelumnya memungkinkan kelas turunan untuk memanggil fungsi anggota dari kelas dasar turunannya secara
private virtual
tidak langsung. Perilaku lama ini salah dan tidak sesuai dengan standar C++. Kompiler tidak lagi menerima kode yang ditulis dengan cara ini, dan mengeluarkan kesalahan kompilator C2280 sebagai hasilnya.error C2280: 'void *S3::__delDtor(unsigned int)': attempting to reference a deleted function
Contoh (sebelumnya)
class base { protected: base(); ~base(); }; class middle : private virtual base {}; class top : public virtual middle {}; void destroy(top *p) { delete p; // }
Contoh (setelah)
class base; // as above class middle : protected virtual base {}; class top : public virtual middle {}; void destroy(top *p) { delete p; }
- atau -
class base; // as above class middle : private virtual base {}; class top : public virtual middle, private virtual bottom {}; void destroy(top *p) { delete p; }
Operator baru yang kelebihan beban dan penghapusan operator
Versi kompilator sebelumnya memungkinkan operator non-anggota menghapus operator baru dan non-anggota untuk dinyatakan statis, dan dideklarasikan dalam namespace selain namespace global. Perilaku lama ini menciptakan risiko bahwa program tidak akan memanggil
new
implementasi ataudelete
operator yang dimaksudkan programmer, menghasilkan perilaku runtime yang buruk diam-diam. Pengkompilasi tidak lagi menerima kode yang ditulis dengan cara ini dan mengeluarkan kesalahan pengkompilasi C2323 sebagai gantinya.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.
Contoh (sebelumnya)
static inline void * __cdecl operator new(size_t cb, const std::nothrow_t&) // error C2323
Contoh (setelah)
void * __cdecl operator new(size_t cb, const std::nothrow_t&) // removed 'static inline'
Selain itu, meskipun pengkompilasi tidak memberikan diagnostik tertentu, operator
new
sebaris dianggap tidak terbentuk.Memanggil ' operator type()' (konversi yang ditentukan pengguna) pada jenis non-kelas
Versi kompilator sebelumnya memungkinkan ' operator type()' untuk dipanggil pada jenis non-kelas sambil mengabaikannya secara diam-diam. Perilaku lama ini menciptakan risiko pembuatan kode buruk senyap, yang mengakibatkan perilaku runtime yang tidak dapat diprediksi. Kompilator tidak lagi menerima kode yang ditulis dengan cara ini dan mengeluarkan kesalahan kompilator C2228 sebagai gantinya.
error C2228: left of '.operator type' must have class/struct/union
Contoh (sebelumnya)
typedef int index_t; void bounds_check(index_t index); void login(int column) { bounds_check(column.operator index_t()); // error C2228 }
Contoh (setelah)
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' }
Nama jenis redundan dalam penentu jenis yang dijabarkan
Versi kompilator sebelumnya diizinkan
typename
dalam penentu jenis yang dijabarkan, tetapi kode yang ditulis dengan cara ini secara semantik salah. Pengkompilasi tidak lagi menerima kode yang ditulis dengan cara ini dan mengeluarkan kesalahan pengkompilasi C3406 sebagai gantinya.error C3406: 'typename' cannot be used in an elaborated type specifier
Contoh (sebelumnya)
template <typename class T> class container;
Contoh (setelah)
template <class T> // alternatively, could be 'template <typename T>'; 'typename' is not elaborating a type specifier in this case class container;
Mengetik pengurangan array dari daftar penginisialisasi
Versi kompilator sebelumnya tidak mendukung pengurangan jenis array dari daftar penginisialisasi. Pengompilasi sekarang mendukung bentuk pengurangan jenis ini dan, sebagai hasilnya, panggilan ke templat fungsi menggunakan daftar penginisialisasi sekarang mungkin ambigu atau kelebihan beban yang berbeda mungkin dipilih daripada di versi kompilator sebelumnya. Untuk mengatasi masalah ini, program sekarang harus secara eksplisit menentukan kelebihan beban yang dimaksudkan programmer.
Ketika perilaku baru ini menyebabkan resolusi kelebihan beban untuk mempertimbangkan kandidat tambahan yang sama baiknya dengan kandidat historis, panggilan menjadi ambigu dan kompilator mengeluarkan kesalahan kompilator C2668 sebagai hasilnya.
error C2668: 'function' : ambiguous call to overloaded function.
Contoh 1: Panggilan ambigu ke fungsi kelebihan beban (sebelumnya)
// 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 }
Contoh 1: panggilan ambigu ke fungsi yang kelebihan beban (setelah)
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); }
Ketika perilaku baru ini menyebabkan resolusi kelebihan beban untuk mempertimbangkan kandidat tambahan yang lebih cocok daripada kandidat historis, panggilan diselesaikan secara tidak ambigu ke kandidat baru, menyebabkan perubahan perilaku program yang mungkin berbeda dari programmer yang dimaksudkan.
Contoh 2: perubahan resolusi kelebihan beban (sebelumnya)
// 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 }); }
Contoh 2: perubahan resolusi kelebihan beban (setelah)
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 }); }
Pemulihan peringatan pernyataan pengalihan
Versi kompilator sebelumnya menghapus beberapa peringatan yang terkait dengan
switch
pernyataan; peringatan ini sekarang telah dipulihkan. Kompiler sekarang mengeluarkan peringatan yang dipulihkan, dan peringatan yang terkait dengan kasus tertentu (termasuk kasus default) sekarang dikeluarkan pada baris yang berisi kasus yang menyinggung, bukan pada baris terakhir pernyataan switch. Akibat dari sekarang mengeluarkan peringatan tersebut pada baris yang berbeda dari di masa lalu, peringatan yang sebelumnya ditekan dengan menggunakan#pragma warning(disable:####)
mungkin tidak lagi ditekan seperti yang dimaksudkan. Untuk menekan peringatan ini seperti yang dimaksudkan, mungkin perlu untuk memindahkan#pragma warning(disable:####)
arahan ke garis di atas kasus pertama yang menyinggung. Berikut ini adalah peringatan yang dipulihkan: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
Contoh C4063 (sebelumnya)
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; } };
Contoh C4063 (setelah)
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; } };
Contoh peringatan lain yang dipulihkan disediakan dalam dokumentasinya.
#include: penggunaan penentu direktori induk '..' dalam nama jalur (hanya mempengaruhi
/Wall
/WX
)Versi kompilator sebelumnya tidak mendeteksi penggunaan penentu direktori induk '..' dalam nama jalur arahan
#include
. Kode yang ditulis dengan cara ini biasanya dimaksudkan untuk menyertakan header yang ada di luar proyek dengan salah menggunakan jalur relatif proyek. Perilaku lama ini menciptakan risiko bahwa program dapat dikompilasi dengan menyertakan file sumber yang berbeda dari programmer yang dimaksudkan, atau bahwa jalur relatif ini tidak akan portabel ke lingkungan build lainnya. Pengkompilasi sekarang mendeteksi dan memberi tahu pemrogram kode yang ditulis dengan cara ini dan mengeluarkan peringatan kompilator opsional C4464, jika diaktifkan.warning C4464: relative include path contains '..'
Contoh (sebelumnya)
#include "..\headers\C4426.h" // emits warning C4464
Contoh (setelah)
#include "C4426.h" // add absolute path to 'headers\' to your project's include directories
Selain itu, meskipun pengkompilasi tidak memberikan diagnostik tertentu, kami juga menyarankan agar penentu direktori induk ".." tidak boleh digunakan untuk menentukan direktori sertakan proyek Anda.
#pragma optimize() memperluas akhir file header sebelumnya (hanya memengaruhi
/Wall
/WX
)Versi kompilator sebelumnya tidak mendeteksi perubahan pada pengaturan bendera pengoptimalan yang lolos dari file header yang disertakan dalam unit terjemahan. Kompilator sekarang mendeteksi dan memberi tahu pemrogram kode yang ditulis dengan cara ini dan mengeluarkan peringatan kompilator opsional C4426 di lokasi yang menyinggung
#include
, jika diaktifkan. Peringatan ini hanya dikeluarkan jika perubahan bertentangan dengan bendera pengoptimalan yang diatur oleh argumen baris perintah ke pengkompilasi.warning C4426: optimization flags changed after including header, may be due to #pragma optimize()
Contoh (sebelumnya)
// C4426.h #pragma optimize("g", off) ... // C4426.h ends // C4426.cpp #include "C4426.h" // warning C4426
Contoh (setelah)
// 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"
Peringatan #pragma yang tidak cocok(push) dan peringatan #pragma (pop) (hanya memengaruhi
/Wall
/WX
)Versi kompilator sebelumnya tidak mendeteksi
#pragma warning(push)
perubahan status dipasangkan dengan#pragma warning(pop)
perubahan status dalam file sumber yang berbeda, yang jarang dimaksudkan. Perilaku lama ini menciptakan risiko bahwa program akan dikompilasi dengan serangkaian peringatan yang berbeda yang diaktifkan dari programmer yang dimaksudkan, mungkin mengakibatkan perilaku runtime yang buruk senyap. Pengkompilasi sekarang mendeteksi dan memberi tahu pemrogram kode yang ditulis dengan cara ini dan mengeluarkan peringatan kompilator opsional C5031 di lokasi pencocokan#pragma warning(pop)
, jika diaktifkan. Peringatan ini mencakup catatan yang mereferensikan lokasi peringatan #pragma yang sesuai(push).warning C5031: #pragma warning(pop): likely mismatch, popping warning state pushed in different file
Contoh (sebelumnya)
// 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 ...
Contoh (setelah)
// 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" ...
Meskipun jarang, kode yang ditulis dengan cara ini terkadang disengaja. Kode yang ditulis dengan cara ini sensitif terhadap perubahan
#include
secara berurutan; jika memungkinkan, sebaiknya file kode sumber mengelola status peringatan dengan cara mandiri.Peringatan #pragma yang tidak cocok(push) (hanya memengaruhi
/Wall
/WX
)Versi kompilator sebelumnya tidak mendeteksi perubahan status yang tidak cocok
#pragma warning(push)
di akhir unit terjemahan. Pengkompilasi sekarang mendeteksi dan memberi tahu pemrogram kode yang ditulis dengan cara ini dan mengeluarkan peringatan kompilator opsional C5032 di lokasi yang tidak cocok#pragma warning(push)
, jika diaktifkan. Peringatan ini hanya dikeluarkan jika tidak ada kesalahan kompilasi di unit terjemahan.warning C5032: detected #pragma warning(push) with no corresponding #pragma warning(pop)
Contoh (sebelumnya)
// 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
Contoh (setelah)
// 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)
Peringatan tambahan mungkin dikeluarkan sebagai akibat dari peningkatan #pragma pelacakan status peringatan
Versi kompilator sebelumnya melacak perubahan status peringatan #pragma tidak cukup baik untuk mengeluarkan semua peringatan yang dimaksudkan. Perilaku ini menciptakan risiko bahwa peringatan tertentu akan secara efektif ditekan dalam keadaan yang berbeda dari programmer yang dimaksudkan. Pengompilasi sekarang melacak
#pragma warning
status dengan lebih kuat -- terutama terkait#pragma warning
dengan perubahan status di dalam templat -- dan secara opsional mengeluarkan peringatan baru C5031 dan C5032, yang dimaksudkan untuk membantu programmer menemukan penggunaan#pragma warning(push)
dan#pragma warning(pop)
yang tidak diinginkan.Sebagai akibat dari peningkatan
#pragma warning
pelacakan perubahan status, peringatan yang sebelumnya salah ditekan atau peringatan yang terkait dengan masalah yang sebelumnya salah didiagnosis mungkin sekarang dikeluarkan.Peningkatan identifikasi kode yang tidak dapat dijangkau
Pustaka Standar C++ mengubah dan meningkatkan kemampuan untuk panggilan fungsi sebaris melalui versi kompilator sebelumnya mungkin memungkinkan pengkompilasi untuk membuktikan bahwa kode tertentu sekarang tidak dapat dijangkau. Perilaku baru ini dapat menghasilkan instans peringatan C4720 baru dan lebih sering dikeluarkan.
warning C4720: unreachable code
Dalam banyak kasus, peringatan ini mungkin hanya dikeluarkan saat mengkompilasi dengan pengoptimalan diaktifkan, karena pengoptimalan dapat menginline lebih banyak panggilan fungsi, menghilangkan kode redundan, atau memungkinkan untuk menentukan bahwa kode tertentu tidak dapat dijangkau. Kami telah mengamati bahwa instans baru peringatan C4720 sering terjadi di blok try/catch , terutama dalam kaitannya dengan penggunaan std::find.
Contoh (sebelumnya)
try { auto iter = std::find(v.begin(), v.end(), 5); } catch (...) { do_something(); // ok }
Contoh (setelah)
try { auto iter = std::find(v.begin(), v.end(), 5); } catch (...) { do_something(); // warning C4702: unreachable code }
Penyempurnaan Kesuaian di Pembaruan 2
Peringatan dan kesalahan tambahan mungkin dikeluarkan sebagai akibat dari dukungan parsial untuk ekspresi SFINAE
Versi kompilator sebelumnya tidak mengurai jenis ekspresi tertentu di dalam
decltype
penentu karena kurangnya dukungan untuk ekspresi SFINAE. Perilaku lama ini salah dan tidak sesuai dengan standar C++. Kompilator sekarang mengurai ekspresi ini dan memiliki dukungan parsial untuk ekspresi SFINAE karena peningkatan kesesuaian yang sedang berlangsung. Akibatnya, pengkompilasi sekarang mengeluarkan peringatan dan kesalahan yang ditemukan dalam ekspresi yang versi kompiler sebelumnya tidak diurai.Ketika perilaku baru ini mengurai
decltype
ekspresi yang menyertakan jenis yang belum dinyatakan, kompilator mengeluarkan kesalahan kompilator C2039 sebagai hasilnya.error C2039: 'type': is not a member of 'global namespace'
Contoh 1: penggunaan jenis yang tidak dinyatakan (sebelumnya)
struct s1 { template < typename T> auto f() - > decltype(s2< T> ::type::f()); // error C2039 template< typename> struct s2 {}; }
Contoh 1 (setelah)
struct s1 { template < typename> // forward declare s2struct s2; template < typename T> auto f() - > decltype(s2< T> ::type::f()); template< typename> struct s2 {}; }
Ketika perilaku baru ini menguraikan
decltype
ekspresi yang kehilangan penggunaantypename
kata kunci yang diperlukan untuk menentukan bahwa nama dependen adalah jenis, pengkompilasi mengeluarkan peringatan kompilator C4346 bersama dengan kesalahan kompilator 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'
Contoh 2: nama dependen bukan jenis (sebelumnya)
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 };
Contoh 2 (setelah)
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
variabel anggota mencegah konstruktor dan operator penugasan yang ditentukan secara implisitVersi kompilator sebelumnya memungkinkan kelas yang memiliki
volatile
variabel anggota untuk memiliki konstruktor salin/pindah default dan operator penugasan salin/pindah default yang dibuat secara otomatis. Perilaku lama ini salah dan tidak sesuai dengan standar C++. Pengkompilasi sekarang mempertimbangkan kelas yang memilikivolatile
variabel anggota untuk memiliki operator konstruksi dan penugasan yang tidak sepele, yang mencegah implementasi default operator ini dihasilkan secara otomatis. Ketika kelas tersebut adalah anggota serikat pekerja (atau serikat anonim di dalam kelas), konstruktor salin/pindah dan operator penetapan salin/pindah dari serikat pekerja (atau kelas yang berisi serikat anonim) akan secara implisit didefinisikan sebagai dihapus. Mencoba membangun atau menyalin serikat (atau kelas yang berisi serikat anonim) tanpa secara eksplisit mendefinisikannya adalah kesalahan dan kompilator mengeluarkan kesalahan kompilator C2280 sebagai hasilnya.error C2280: 'B::B(const B &)': attempting to reference a deleted function
Contoh (sebelumnya)
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
Contoh (setelah)
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
Fungsi anggota statis tidak mendukung kualifikasi cv.
Versi Visual Studio 2015 sebelumnya memungkinkan fungsi anggota statis memiliki kualifikasi cv. Perilaku ini disebabkan oleh regresi di Visual Studio 2015 dan Visual Studio 2015 Update 1; Visual Studio 2013 dan versi sebelumnya dari compiler menolak kode yang ditulis dengan cara ini. Perilaku Visual Studio 2015 dan Visual Studio 2015 Update 1 salah dan tidak sesuai dengan standar C++. Visual Studio 2015 Update 2 menolak kode yang ditulis dengan cara ini dan mengeluarkan kesalahan kompilator C2511 sebagai gantinya.
error C2511: 'void A::func(void) const': overloaded member function not found in 'A'
Contoh (sebelumnya)
struct A { static void func(); }; void A::func() const {} // C2511
Contoh(setelah)
struct A { static void func(); }; void A::func() {} // removed const
Deklarasi penerusan enum tidak diizinkan dalam kode WinRT (hanya mempengaruhi
/ZW
)Kode yang dikompilasi untuk Windows Runtime (WinRT) tidak memungkinkan
enum
jenis untuk diteruskan dideklarasikan, mirip dengan ketika kode C++ terkelola dikompilasi untuk .Net Framework menggunakan/clr
sakelar pengkompilasi. Perilaku ini memastikan bahwa ukuran enumerasi selalu diketahui dan dapat diproyeksikan dengan benar ke sistem jenis WinRT. Pengkompilasi menolak kode yang ditulis dengan cara ini dan mengeluarkan kesalahan kompilator C2599 bersama dengan kesalahan kompilator C3197.error C2599: 'CustomEnum': the forward declaration of a WinRT enum is not allowed
error C3197: 'public': can only be used in definitions
Contoh (sebelumnya)
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; } };
Contoh (setelah)
// forward declaration of CustomEnum removed namespace A { public enum class CustomEnum : int32 { Value1 }; } public ref class Component sealed { public: CustomEnum f() { return CustomEnum::Value1; } };
Operator non-anggota yang kelebihan beban baru dan penghapusan operator mungkin tidak dinyatakan sebaris (Tingkat 1 (
/W1
) secara default)Versi kompilator sebelumnya tidak mengeluarkan peringatan ketika operator non-anggota baru dan fungsi penghapusan operator dinyatakan sebaris. Kode yang ditulis dengan cara ini tidak terbentuk buruk (tidak diperlukan diagnostik) dan dapat menyebabkan masalah memori yang diakibatkan oleh operator baru dan penghapusan yang tidak cocok (terutama ketika digunakan bersama dengan dealokasi berukuran) yang dapat sulit didiagnosis. Kompilator sekarang mengeluarkan peringatan kompilator C4595 untuk membantu mengidentifikasi kode yang ditulis dengan cara ini.
warning C4595: 'operator new': non-member operator new or delete functions may not be declared inline
Contoh (sebelumnya)
inline void* operator new(size_t sz) // warning C4595 { ... }
Contoh (setelah)
void* operator new(size_t sz) // removed inline { ... }
Memperbaiki kode yang ditulis dengan cara ini mungkin mengharuskan definisi operator dipindahkan dari file header dan ke file sumber yang sesuai.
Penyempurnaan Kesuaian di Pembaruan 3
std::is_convertable sekarang mendeteksi penugasan mandiri (pustaka standar)
Versi sebelumnya dari
std::is_convertable
type-trait tidak mendeteksi penetapan sendiri jenis kelas dengan benar saat konstruktor salinannya dihapus atau privat. Sekarang,std::is_convertable<>::value
diatur dengan benar kefalse
saat diterapkan ke jenis kelas dengan konstruktor salinan yang dihapus atau privat.Tidak ada diagnostik kompilator yang terkait dengan perubahan ini.
Contoh
#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");
Dalam versi compiler sebelumnya, pernyataan statis di bagian bawah contoh ini lulus karena
std::is_convertable<>::value
salah diatur ketrue
. Sekarang,std::is_convertable<>::value
diatur dengan benar kefalse
, menyebabkan pernyataan statis gagal.Salinan sepele default atau dihapus dan memindahkan konstruktor menghormati penentu akses
Versi kompilator sebelumnya tidak memeriksa penentu akses salinan sepele default atau dihapus dan memindahkan konstruktor sebelum memungkinkan mereka dipanggil. Perilaku lama ini salah dan tidak sesuai dengan standar C++. Dalam beberapa kasus, perilaku lama ini menciptakan risiko pembuatan kode buruk senyap, yang mengakibatkan perilaku runtime yang tidak dapat diprediksi. Pengkompilasi sekarang memeriksa penentu akses salinan sepele default atau dihapus dan memindahkan konstruktor untuk menentukan apakah konstruktor dapat dipanggil, dan jika tidak, mengeluarkan peringatan kompilator C2248 sebagai hasilnya.
error C2248: 'S::S' cannot access private member declared in class 'S'
Contoh (sebelumnya)
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 }
Contoh (setelah)
class S { public: S() = default; private: S(const S&) = default; }; void f(const S&); // pass S by reference int main() { S s; f(s); }
Penghentian dukungan kode ATL yang diatribusikan (Tingkat 1 (
/W1
) secara default)Versi sebelumnya dari pengkompilasi yang didukung mengaitkan kode ATL. Sebagai fase berikutnya menghapus dukungan untuk kode ATL atribut yang dimulai di Visual Studio 2008, kode ATL yang diatribusikan telah ditolak. Kompilator sekarang mengeluarkan peringatan kompilator C4467 untuk membantu mengidentifikasi jenis kode yang tidak digunakan lagi ini.
warning C4467: Usage of ATL attributes is deprecated
Jika Anda ingin terus menggunakan kode ATL yang diatribusikan hingga dukungan dihapus dari pengkompilasi, Anda dapat menonaktifkan peringatan ini dengan meneruskan
/Wv:18
argumen baris perintah atau/wd:4467
ke pengkompilasi, atau dengan menambahkan#pragma warning(disable:4467)
dalam kode sumber Anda.Contoh 1 (sebelumnya)
[uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")] class A {};
Contoh 1 (setelah)
__declspec(uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")) A {};
Terkadang Anda mungkin memerlukan atau ingin membuat file IDL untuk menghindari penggunaan atribut ATL yang tidak digunakan lagi, seperti dalam contoh kode di bawah ini
Contoh 2 (sebelumnya)
[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 { // ... };
Pertama, buat file *.idl; file vc140.idl yang dihasilkan dapat digunakan untuk mendapatkan file *.idl yang berisi antarmuka dan anotasi.
Selanjutnya, tambahkan langkah MIDL ke build Anda untuk memastikan bahwa definisi antarmuka C++ dihasilkan.
Contoh 2 IDL (setelah)
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; }; }
Kemudian, gunakan ATL langsung dalam file implementasi, seperti dalam contoh kode di bawah ini.
Contoh 2 Implementasi (setelah)
#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() };
File header (PCH) yang telah dikommpilasikan sebelumnya dan direktif #include yang tidak cocok (hanya memengaruhi
/Wall
/WX
)Versi kompilator sebelumnya menerima direktif yang tidak cocok
#include
dalam file sumber antara-Yc
dan-Yu
kompilasi saat menggunakan file header (PCH) yang telah dikompilasi sebelumnya. Kode yang ditulis dengan cara ini tidak lagi diterima oleh pengkompilasi. Kompilator sekarang mengeluarkan peringatan kompilator CC4598 untuk membantu mengidentifikasi direktif yang tidak cocok#include
saat menggunakan file PCH.warning C4598: 'b.h': included header file specified for Ycc.h at position 2 does not match Yuc.h at that position
Contoh (sebelumnya):
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"
Contoh (setelah)
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"
File header (PCH) yang telah dikompresi dan tidak cocok menyertakan direktori (hanya memengaruhi
/Wall
/WX
)Versi kompilator sebelumnya yang diterima tidak cocok termasuk argumen baris perintah direktori (
-I
) ke kompilator antara-Yc
dan-Yu
kompilasi saat menggunakan file header (PCH) yang telah dikompilasi sebelumnya. Kode yang ditulis dengan cara ini tidak lagi diterima oleh pengkompilasi. Pengkompilasi sekarang mengeluarkan peringatan kompilator CC4599 untuk membantu mengidentifikasi argumen baris perintah include directory (-I
) yang tidak cocok saat menggunakan file PCH.warning C4599: '-I..' : specified for Ycc.h at position 1 does not match Yuc.h at that position
Contoh (sebelumnya)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h Z.cpp
Contoh (setelah)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h -I.. Z.cpp
Perubahan Kesuaian Visual Studio 2013
Kompilator
Kata kunci akhir sekarang menghasilkan kesalahan simbol yang tidak terselesaikan di mana kata kunci tersebut akan dikompilasi sebelumnya:
struct S1 { virtual void f() = 0; }; struct S2 final : public S1 { virtual void f(); }; int main(S2 *p) { p->f(); }
Dalam versi sebelumnya, kesalahan tidak dikeluarkan karena panggilan adalah
virtual
panggilan; namun, program akan mengalami crash saat runtime. Sekarang, kesalahan linker dikeluarkan karena kelas diketahui final. Dalam contoh ini, untuk memperbaiki kesalahan, Anda akan menautkan terhadap obj yang berisi definisiS2::f
.Ketika Anda menggunakan fungsi teman di namespace, Anda harus mendeklarasi ulang fungsi teman sebelum merujuknya atau Anda akan mendapatkan kesalahan karena kompilator sekarang sesuai dengan ISO C++ Standard. Misalnya, contoh ini tidak lagi mengkompilasi:
namespace NS { class C { void func(int); friend void func(C* const) {} }; void C::func(int) { NS::func(this); // error } }
Untuk memperbaiki kode ini, deklarasikan
friend
fungsi: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); }
Standar C++ tidak mengizinkan spesialisasi eksplisit di kelas. Meskipun pengkompilasi Microsoft C++ memungkinkannya dalam beberapa kasus, dalam kasus seperti contoh berikut, kesalahan sekarang dihasilkan karena pengkompilasi tidak menganggap fungsi kedua sebagai spesialisasi yang pertama.
template < int N> class S { public: template void f(T& val); template < > void f(char val); }; template class S< 1>;
Untuk memperbaiki kode ini, ubah fungsi kedua:
template <> void f(char& val);
Pengkompilasi tidak lagi mencoba memisahkan dua fungsi dalam contoh berikut, dan sekarang memancarkan kesalahan:
template< typename T> void Func(T* t = nullptr); template< typename T> void Func(...); int main() { Func< int>(); // error }
Untuk memperbaiki kode ini, klarifikasi panggilan:
template< typename T> void Func(T* t = nullptr); template< typename T> void Func(...); int main() { Func< int>(nullptr); // ok }
Sebelum pengkompilasi sesuai dengan ISO C++11, kode berikut akan dikompilasi dan menyebabkan
x
penyelesaian untuk mengetikint
:auto x = {0}; int y = x;
Kode ini sekarang diselesaikan
x
ke jenisstd::initializer_list<int>
dan menyebabkan kesalahan pada baris berikutnya yang mencoba menetapkanx
untuk mengetikint
. (Tidak ada konversi secara default.) Untuk memperbaiki kode ini, gunakanint
untuk menggantiauto
:int x = {0}; int y = x;
Inisialisasi agregat tidak lagi diizinkan ketika jenis nilai sebelah kanan tidak cocok dengan jenis nilai sebelah kiri yang sedang diinisialisasi, dan kesalahan dikeluarkan karena ISO C++11 Standard memerlukan inisialisasi seragam untuk bekerja tanpa mempersempit konversi. Sebelumnya, jika konversi yang dipersempit tersedia, peringatan Compiler Warning (level 4) C4242 akan dikeluarkan alih-alih kesalahan.
int i = 0; char c = {i}; // error
Untuk memperbaiki kode ini, tambahkan konversi penyempitan eksplisit:
int i = 0; char c = {static_cast<char>(i)};
Inisialisasi berikut tidak lagi diizinkan:
void *p = {{0}};
Untuk memperbaiki kode ini, gunakan salah satu formulir ini:
void *p = 0; // or void *p = {0};
Pencarian nama telah berubah. Kode berikut diselesaikan secara berbeda di pengkompilasi C++ di Visual Studio 2012 dan Visual Studio 2013:
enum class E1 { a }; enum class E2 { b }; int main() { typedef E2 E1; E1::b; }
Di Visual Studio 2012,
E1
ekspresiE1::b
dalam diselesaikan::E1
dalam cakupan global. Di Visual Studio 2013,E1
dalam ekspresiE1::b
diselesaikan ketypedef E2
definisi dimain()
dan memiliki jenis::E2
.Tata letak objek telah berubah. Pada x64, tata letak objek kelas dapat berubah dari rilis sebelumnya. Jika memiliki
virtual
fungsi tetapi tidak memiliki kelas dasar yang memilikivirtual
fungsi, model objek pengkompilasi menyisipkan penunjuk kevirtual
tabel fungsi setelah tata letak anggota data. Ini berarti tata letak mungkin tidak optimal dalam semua kasus. Dalam rilis sebelumnya, pengoptimalan untuk x64 akan mencoba meningkatkan tata letak untuk Anda, tetapi karena gagal berfungsi dengan benar dalam situasi kode yang kompleks, pengoptimalan akan dihapus di Visual Studio 2013. Misalnya, pertimbangkan kode ini:__declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };
Di Visual Studio 2013, hasil pada
sizeof(S2)
x64 adalah 48, tetapi dalam rilis sebelumnya, ini mengevaluasi ke 32. Untuk membuat ini mengevaluasi ke 32 di pengkompilasi Visual Studio 2013 C++ untuk x64, tambahkan kelas dasar dummy yang memilikivirtual
fungsi:__declspec(align(16)) struct S1 { }; struct dummy { virtual ~dummy() {} }; struct S2 : public dummy { virtual ~S2(); void *p; S1 s; };
Untuk menemukan tempat dalam kode Anda yang akan dioptimalkan oleh rilis sebelumnya, gunakan kompilator dari rilis tersebut
/W3
bersama dengan opsi kompilator dan aktifkan peringatan C4370. Contohnya:#pragma warning(default:4370) __declspec(align(16)) struct S1 { }; struct S2 { virtual ~S2(); void *p; S1 s; };
Sebelum Visual Studio 2013, kode ini menghasilkan pesan ini: "peringatan C4370: 'S2' : tata letak kelas telah berubah dari versi kompiler sebelumnya karena pengemasan yang lebih baik".
Pengkompilasi x86 memiliki masalah tata letak suboptimal yang sama di semua versi pengkompilasi. Misalnya, jika kode ini dikompilasi untuk x86:
struct S { virtual ~S(); int i; double d; };
Hasilnya
sizeof(S)
adalah 24. Namun, dapat dikurangi menjadi 16 jika Anda menggunakan solusi yang disebutkan untuk x64:struct dummy { virtual ~dummy() {} }; struct S : public dummy { virtual ~S(); int i; double d; };
Pustaka Standar
Pengkompilasi C++ di Visual Studio 2013 mendeteksi ketidakcocokan dalam _ITERATOR_DEBUG_LEVEL, yang diterapkan di Visual Studio 2010, dan ketidakcocokan RuntimeLibrary. Ketidakcocokan ini terjadi ketika opsi /MT
kompilator (rilis statis), /MTd
(debug statis), /MD
(rilis dinamis), dan /MDd
(debug dinamis) dicampur.
Jika kode Anda mengakui templat alias simulasi rilis sebelumnya, Anda harus mengubahnya. Misalnya, alih-alih
allocator_traits<A>::rebind_alloc<U>::other
, sekarang Anda harus mengatakanallocator_traits<A>::rebind_alloc<U>
. Meskipunratio_add<R1, R2>::type
tidak lagi diperlukan dan kami sekarang menyarankan Anda mengatakanratio_add<R1, R2>
, yang pertama akan tetap dikompilasi karenaratio<N, D>
diperlukan untuk memiliki typedef "jenis" untuk rasio yang dikurangi, yang akan menjadi jenis yang sama jika sudah berkurang.Anda harus menggunakan
#include <algorithm>
ketika Anda memanggilstd::min()
ataustd::max()
.Jika kode Anda yang ada menggunakan enum cakupan simulasi rilis sebelumnya—enum tradisional yang tidak tercakup yang dibungkus dalam namespace—Anda harus mengubahnya. Misalnya, jika Anda merujuk ke jenis
std::future_status::future_status
, sekarang Anda harus mengatakanstd::future_status
. Namun, sebagian besar kode tidak terpengaruh—misalnya,std::future_status::ready
masih dikompilasi.explicit operator bool()
lebih ketat daripada operator unspecified-bool-type().explicit operator bool()
mengizinkan konversi eksplisit ke bool—misalnya, diberikanshared_ptr<X> sp
, baikstatic_cast<bool>(sp)
danbool b(sp)
valid—dan "konversi kontekstual" yang dapat diuji Boolean ke bool—misalnya,if (sp)
,!sp
,sp &&
apa pun. Namun,explicit operator bool()
melarang konversi implisit ke bool, sehingga Anda tidak dapat mengatakanbool b = sp;
dan diberi jenis pengembalian bool, Anda tidak dapat mengatakanreturn sp
.Sekarang templat variadik nyata diimplementasikan, _VARIADIC_MAX dan makro terkait tidak berpengaruh. Jika Anda masih menentukan _VARIADIC_MAX, itu diabaikan. Jika Anda mengakui mesin makro kami yang dimaksudkan untuk mendukung templat variadik yang disimulasikan dengan cara lain, Anda harus mengubah kode Anda.
Selain kata kunci biasa, header Pustaka Standar C++ sekarang melarang penggantian makro kata kunci peka konteks dan akhir.
reference_wrapper
,ref()
, dancref()
sekarang melarang pengikatan ke objek sementara.<random>
sekarang secara ketat memberlakukan prasyarat waktu kompilasinya.Berbagai sifat jenis Pustaka Standar C++ memiliki prasyarat "T akan menjadi jenis lengkap". Meskipun kompilator sekarang memberlakukan prasyarat ini lebih ketat, itu mungkin tidak memberlakukannya dalam semua situasi. (Karena pelanggaran prasyarat Pustaka Standar C++ memicu perilaku yang tidak ditentukan, Standar tidak menjamin penegakan.)
Pustaka Standar C++ tidak mendukung
/clr:oldSyntax
.Spesifikasi C++11 untuk
common_type<>
memiliki konsekuensi yang tidak terduga dan tidak diinginkan; khususnya, itu membuatcommon_type<int, int>::type
pengembalianint&&
. Oleh karena itu, kompilator mengimplementasikan Resolusi yang Diusulkan untuk Masalah Grup Kerja Pustaka 2141, yang membuatcommon_type<int, int="">::type
pengembalianint
.Sebagai efek samping dari perubahan ini, kasus identitas tidak lagi berfungsi (
common_type<T>
tidak selalu menghasilkan jenisT
). Perilaku ini sesuai dengan Resolusi yang Diusulkan, tetapi melanggar kode apa pun yang bergantung pada perilaku sebelumnya.Jika Anda memerlukan sifat jenis identitas, jangan gunakan non-standar
std::identity
yang ditentukan karena<type_traits>
tidak akan berfungsi untuk<void>
. Sebagai gantinya, terapkan sifat jenis identitas Anda sendiri agar sesuai dengan kebutuhan Anda. Berikut contohnya:template < typename T> struct Identity { typedef T type; };
MFC dan ATL
Hanya Visual Studio 2013: Pustaka MFC MBCS tidak disertakan dalam Visual Studio karena Unicode sangat populer dan penggunaan MBCS telah menurun secara signifikan. Perubahan ini juga membuat MFC lebih selaras dengan Windows SDK itu sendiri, karena banyak kontrol dan pesan baru hanya Unicode. Namun, jika Anda harus terus menggunakan pustaka MFC MBCS, Anda dapat mengunduhnya dari Pusat Unduhan Microsoft di Pustaka MFC Multibyte untuk Visual Studio 2013. Paket Visual C++ Redistributable masih menyertakan pustaka ini. (Catatan: DLL MBCS disertakan dalam komponen penyiapan C++ di Visual Studio 2015 dan yang lebih baru).
Aksesibilitas untuk pita MFC diubah. Alih-alih arsitektur satu tingkat, sekarang ada arsitektur hierarkis. Anda masih dapat menggunakan perilaku lama dengan memanggil
CRibbonBar::EnableSingleLevelAccessibilityMode()
.CDatabase::GetConnect
metode dihapus. Untuk meningkatkan keamanan, string koneksi sekarang disimpan dienkripsi dan didekripsi hanya sesuai kebutuhan; tidak dapat dikembalikan sebagai teks biasa. String dapat diperoleh dengan menggunakanCDatabase::Dump
metode .CWnd::OnPowerBroadcast
Tanda tangan diubah. Tanda tangan handler pesan ini diubah untuk mengambil LPARAM sebagai parameter kedua.Tanda tangan diubah untuk mengakomodasi penanganan pesan. Daftar parameter fungsi berikut telah diubah untuk menggunakan penangan pesan ON_WM_* yang baru ditambahkan:
CWnd::OnDisplayChange
diubah ke (UINT, int, int) alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_DISPLAYCHANGE baru dapat digunakan di peta pesan.CFrameWnd::OnDDEInitiate
diubah ke (CWnd*, UINT, UNIT) alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_DDE_INITIATE baru dapat digunakan di peta pesan.CFrameWnd::OnDDEExecute
diubah ke (CWnd*, HANDLE) alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_DDE_EXECUTE baru dapat digunakan di peta pesan.CFrameWnd::OnDDETerminate
diubah menjadi (CWnd*) sebagai parameter alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_DDE_TERMINATE baru dapat digunakan di peta pesan.CMFCMaskedEdit::OnCut
diubah menjadi tidak ada parameter alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_CUT baru dapat digunakan di peta pesan.CMFCMaskedEdit::OnClear
diubah menjadi tidak ada parameter alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_CLEAR baru dapat digunakan dalam peta pesan.CMFCMaskedEdit::OnPaste
diubah menjadi tidak ada parameter alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_PASTE baru dapat digunakan di peta pesan.
#ifdef
direktif dalam file header MFC dihapus.#ifdef
Banyak arahan dalam file header MFC yang terkait dengan versi Windows yang tidak didukung (WINVER < 0x0501
) dihapus.ATL DLL (atl120.dll) dihapus. ATL sekarang disediakan sebagai header dan pustaka statis (atls.lib).
Atlsd.lib, atlsn.lib, dan atlsnd.lib dihapus. Atls.lib tidak lagi memiliki dependensi atau kode set karakter yang khusus untuk debug/rilis. Karena berfungsi sama untuk Unicode/ANSI dan debug/rilis, hanya satu versi pustaka yang diperlukan.
Alat ATL/MFC Trace dihapus bersama dengan ATL DLL, dan mekanisme pelacakan disederhanakan.
CTraceCategory
Konstruktor sekarang mengambil satu parameter (nama kategori), dan makro TRACE memanggil fungsi pelaporan debug CRT.
Perubahan Melanggar Visual Studio 2012
Kompilator
Opsi
/Yl
pengkompilasi telah berubah. Secara default, pengkompilasi menggunakan opsi ini, yang dapat menyebabkan kesalahan LNK2011 dalam kondisi tertentu. Untuk informasi selengkapnya, lihat /Yl (Menyuntikkan Referensi PCH untuk Pustaka Debug).Dalam kode yang dikompilasi dengan menggunakan
/clr
,enum
kata kunci kelas mendefinisikan enum C++11, bukan enum runtime bahasa umum (CLR). Untuk menentukan enum CLR, Anda harus eksplisit tentang aksesibilitasnya.Gunakan kata kunci templat untuk secara eksplisit mendisambiguasi nama dependen (kesesuaian Standar Bahasa C++). Dalam contoh berikut, kata kunci templat yang disorot wajib untuk mengatasi ambiguitas. Untuk informasi selengkapnya, lihat Resolusi Nama untuk Jenis Dependen.
template < typename X = "", typename = "" AY = ""> struct Container { typedef typename AY::template Rebind< X> ::Other AX; };
Ekspresi konstan jenis float tidak lagi diizinkan sebagai argumen templat, seperti yang ditunjukkan dalam contoh berikut.
template<float n=3.14> struct B {}; // error C2993: 'float': illegal type for non-type template parameter 'n'
Kode yang dikompilasi dengan menggunakan
/GS
opsi baris perintah dan yang memiliki kerentanan off-by-one dapat menyebabkan penghentian proses pada runtime, seperti yang ditunjukkan dalam contoh pseudocode berikut.char buf[MAX]; int cch; ManipulateString(buf, &cch); // ... buf[cch] = '\0'; // if cch >= MAX, process will terminate
Arsitektur default untuk build x86 diubah menjadi SSE2; oleh karena itu, kompilator dapat memancarkan instruksi SSE, dan akan menggunakan register XMM untuk melakukan perhitungan floating-point. Jika Anda ingin kembali ke perilaku sebelumnya, gunakan
/arch:IA32
bendera pengkompilasi untuk menentukan arsitektur sebagai IA32.Kompilator dapat mengeluarkan peringatan Compiler Warning (tingkat 4) C4703 dan C4701 di mana sebelumnya tidak. Pengkompilasi menerapkan pemeriksaan yang lebih kuat untuk penggunaan variabel lokal jenis pointer yang tidak diinisialisasi.
Ketika bendera
/HIGHENTROPYVA
linker baru ditentukan, Windows 8 biasanya menyebabkan alokasi memori mengembalikan alamat 64-bit. (Sebelum Windows 8, alokasi tersebut lebih sering mengembalikan alamat yang kurang dari 2 GB.) Perubahan ini dapat mengekspos bug pemotongan pointer dalam kode yang ada. Secara default, sakelar ini aktif. Untuk menonaktifkan perilaku ini, tentukan/HIGHENTROPYVA:NO
.Pengkompilasi terkelola (Visual Basic/C#) juga mendukung
/HIGHENTROPYVA
build terkelola. Namun, dalam hal ini,/HIGHENTROPYVAswitch
nonaktif secara default.
IDE
- Meskipun kami menyarankan agar Anda tidak membuat aplikasi Formulir Windows di C++/CLI, pemeliharaan aplikasi UI C++/CLI yang ada didukung. Jika Anda harus membuat aplikasi Formulir Windows, atau aplikasi UI .NET lainnya, gunakan C# atau Visual Basic. Gunakan C++/CLI hanya untuk tujuan interoperabilitas.
Pustaka Pola Paralel dan Pustaka Runtime Konkurensi
Enumerasi SchedulerType
UmsThreadDefault
tidak digunakan lagi. Spesifikasi UmsThreadDefault
menghasilkan peringatan yang tidak digunakan lagi, dan secara internal memetakan kembali ke ThreadScheduler
.
Pustaka Standar
Setelah perubahan mencolok antara standar C++98/03 dan C++11, menggunakan argumen templat eksplisit untuk dipanggil
make_pair()
— seperti dalam — biasanya tidak dikompilasimake_pair<int, int>(x, y)
di Visual C++ di Visual Studio 2012. Solusinya adalah selalu memanggilmake_pair()
tanpa argumen templat eksplisit — seperti dalammake_pair(x, y)
. Menyediakan argumen templat eksplisit mengalahkan tujuan fungsi. Jika Anda memerlukan kontrol yang tepat atas jenis yang dihasilkan, gunakanpair
alih-alihmake_pair
— seperti dalampair<short, short>(int1, int2)
.Perubahan melanggar lainnya antara standar C++98/03 dan C++11: Ketika A secara implisit dapat dikonversi ke B dan B secara implisit dapat dikonversi ke C, tetapi A tidak secara implisit dapat dikonversi ke C, C++98/03 dan Visual Studio 2010 diizinkan
pair<A, X>
untuk dikonversi (secara implisit atau eksplisit) kepair<C, X>
. (Jenis lain, X, tidak menarik di sini, dan tidak spesifik untuk jenis pertama dalam pasangan.) Pengkompilasi C++ di Visual Studio 2012 mendeteksi bahwa A tidak secara implisit dapat dikonversi ke C, dan menghapus konversi pasangan dari resolusi kelebihan beban. Perubahan ini positif untuk banyak skenario. Misalnya, kelebihan bebanfunc(const pair<int, int>&)
danfunc(const pair<string, string>&)
, dan panggilanfunc()
denganpair<const char *, const char *>
akan dikompilasi dengan perubahan ini. Namun, perubahan ini merusak kode yang bergantung pada konversi pasangan agresif. Kode tersebut biasanya dapat diperbaiki dengan melakukan satu bagian dari konversi secara eksplisit—misalnya, dengan meneruskanmake_pair(static_cast<B>(a), x)
ke fungsi yang mengharapkanpair<C, X>
.Templat variadik yang disimulasikan Visual Studio 2010—misalnya,
make_shared<T>(arg1, arg2, argN)
—hingga batas 10 argumen, dengan memberi stempel kelebihan beban dan spesialisasi dengan mesin pra-prosesor. Di Visual Studio 2012, batas ini dikurangi menjadi lima argumen untuk meningkatkan waktu kompilasi dan mengkompilasi konsumsi memori untuk sebagian besar pengguna. Namun, Anda dapat menetapkan batas sebelumnya dengan secara eksplisit menentukan _VARIADIC_MAX sebagai 10, di seluruh proyek.C++11 17.6.4.3.1 [macro.names]/2 melarang penggantian makro kata kunci ketika header Pustaka Standar C++ disertakan. Header sekarang memancarkan kesalahan pengkompilasi jika mendeteksi kata kunci yang diganti makro. (Mendefinisikan _ALLOW_KEYWORD_MACROS memungkinkan kode tersebut untuk dikompilasi, tetapi kami sangat mencegah penggunaan tersebut.) Sebagai pengecualian, bentuk
new
makro diizinkan secara default, karena header secara komprehensif mempertahankan diri dengan menggunakan/#pragma push_macro("new")
#undef new
/#pragma pop_macro("new")
. Menentukan _ENFORCE_BAN_OF_MACRO_NEW melakukan apa yang namanya tersirat.Untuk menerapkan berbagai pengoptimalan dan pemeriksaan penelusuran kesalahan, implementasi Pustaka Standar C++ sengaja merusak kompatibilitas biner di antara versi Visual Studio (2005, 2008, 2010, 2012). Ketika Pustaka Standar C++ digunakan, pustaka ini melarang pencampuran file objek dan pustaka statis yang dikompilasi dengan menggunakan versi yang berbeda ke dalam satu biner (EXE atau DLL), dan melarang melewati objek Pustaka Standar C++ antara biner yang dikompilasi dengan menggunakan versi yang berbeda. Pencampuran file objek dan pustaka statis (menggunakan Pustaka Standar C++ yang dikompilasi dengan menggunakan Visual Studio 2010 dengan yang dikompilasi dengan menggunakan pengkompilasi C++ di Visual Studio 2012 memancarkan kesalahan linker tentang _MSC_VER ketidakcocokan, di mana _MSC_VER adalah makro yang berisi versi utama pengkompilasi (1700 untuk Visual C++ di Visual Studio 2012). Pemeriksaan ini tidak dapat mendeteksi pencampuran DLL, dan tidak dapat mendeteksi pencampuran yang melibatkan Visual Studio 2008 atau yang lebih lama.
Selain mendeteksi ketidakcocokan _ITERATOR_DEBUG_LEVEL, yang diterapkan di Visual Studio 2010, pengkompilasi C++ di Visual Studio 2012 mendeteksi ketidakcocokan Pustaka Runtime. Ketidakcocokan ini terjadi ketika opsi
/MT
pengkompilasi (rilis statis),/MTd
(debug statis),/MD
(rilis dinamis), dan/MDd
(debug dinamis) dicampur.operator<()
, ,operator>()
operator<=()
, danoperator>=()
sebelumnya tersedia untukstd::unordered_map
keluarga kontainer danstdext::hash_map
, meskipun implementasinya tidak berguna. Operator non-standar ini telah dihapus di Visual C++ di Visual Studio 2012. Selain itu, pelaksanaanoperator==()
danoperator!=()
untukstd::unordered_map
keluarga telah diperpanjang untuk mencakupstdext::hash_map
keluarga. (Kami menyarankan agar Anda menghindari penggunaanstdext::hash_map
keluarga dalam kode baru.)C++11 22.4.1.4 [locale.codecvt] menentukan bahwa dan
codecvt::do_length()
harus mengambil parameter yangcodecvt::length()
dapatstateT&
dimodifikasi, tetapi Visual Studio 2010 mengambilconst stateT&
. Pengkompilasi C++ di Visual Studio 2012 diambilstateT&
sebagaimana diamanatkan oleh standar. Perbedaan ini signifikan bagi siapa saja yang mencoba mengambil alih fungsido_length()
virtual .
CRT
Timbunan C Runtime (CRT), yang digunakan untuk baru dan malloc(), tidak lagi privat. CRT sekarang menggunakan timbunan proses. Ini berarti bahwa tumpukan tidak dihancurkan ketika DLL dibongkar, sehingga DLL yang menautkan secara statis ke CRT harus memastikan memori yang dialokasikan oleh kode DLL dibersihkan sebelum dibongkar.
Fungsi ini
iscsymf()
menegaskan dengan nilai negatif.Struktur
threadlocaleinfostruct
telah berubah untuk mengakomodasi perubahan pada fungsi lokal.Fungsi CRT yang memiliki intrinsik yang sesuai seperti
memxxx()
,strxxx()
dihapus dari intrin.h. Jika Anda menyertakan intrin.h hanya untuk fungsi-fungsi ini, Anda sekarang harus menyertakan header CRT yang sesuai.
MFC dan ATL
Dukungan Fusion yang dihapus (afxcomctl32.h); oleh karena itu, semua metode yang didefinisikan dalam
<afxcomctl32.h>
telah dihapus. File header<afxcomctl32.h>
dan<afxcomctl32.inl>
telah dihapus.Mengubah nama menjadi
CDockablePane::RemoveFromDefaultPaneDividier
CDockablePane::RemoveFromDefaultPaneDivider
.Mengubah tanda tangan
CFileDialog::SetDefExt
untuk menggunakan LPCTSTR; oleh karena itu, build Unicode terpengaruh.Menghapus kategori pelacakan ATL usang.
Mengubah tanda tangan
CBasePane::MoveWindow
untuk mengambilconst CRect
.Mengubah tanda tangan
CMFCEditBrowseCtrl::EnableBrowseButton
.Menghapus
m_fntTabs
danm_fntTabsBold
dariCMFCBaseTabCtrl
.Menambahkan parameter ke
CMFCRibbonStatusBarPane
konstruktor. (Ini adalah parameter default, sehingga tidak melanggar sumber.)Menambahkan parameter ke
CMFCRibbonCommandsListBox
konstruktor. (Ini adalah parameter default, sehingga tidak melanggar sumber.)AFXTrackMouse
Menghapus API (dan proc timer terkait). Gunakan API Win32TrackMouseEvent
sebagai gantinya.Menambahkan parameter ke
CFolderPickerDialog
konstruktor. (Ini adalah parameter default, sehingga tidak melanggar sumber.)CFileStatus
ukuran struktur berubah: Anggotam_attribute
berubah dari BYTE ke DWORD (agar sesuai dengan nilai yang dikembalikan dariGetFileAttributes
).CRichEditCtrl
danCRichEditView
gunakan MSFTEDIT_CLASS (kontrol RichEdit 4.1) alih-alih RICHEDIT_CLASS (kontrol RichEdit 3.0) dalam build Unicode.Dihapus
AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackground
karena selalu TRUE pada Windows Vista, Windows 7, dan Windows 8.Dihapus
AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailable
karena selalu TRUE pada Windows Vista, Windows 7, dan Windows 8.Dihapus
AFX_GLOBAL_DATA::DwmExtendFrameIntoClientArea
. Panggil Windows API langsung di Windows Vista, Windows 7, dan Windows 8.Dihapus
AFX_GLOBAL_DATA::DwmDefWindowProc
. Panggil Windows API langsung di Windows Vista, Windows 7, dan Windows 8.Diganti namanya
AFX_GLOBAL_DATA::DwmIsCompositionEnabled
menjadiIsDwmCompositionEnabled
untuk menghilangkan tabrakan nama.Mengubah pengidentifikasi untuk sejumlah timer internal MFC dan memindahkan definisi ke afxres.h (AFX_TIMER_ID_*).
Mengubah tanda tangan
OnExitSizeMove
metode untuk setuju dengan makro ON_WM_EXITSIZEMOVE:CFrameWndEx
CMDIFrameWndEx
CPaneFrameWnd
Mengubah nama dan tanda tangan
OnDWMCompositionChanged
untuk setuju dengan makro ON_WM_DWMCOMPOSITIONCHANGED:CFrameWndEx
CMDIFrameWndEx
CPaneFrameWnd
Mengubah tanda tangan
OnMouseLeave
metode untuk menyetujui makro ON_WM_MOUSELEAVE:CMFCCaptionBar
CMFCColorBar
CMFCHeaderCtrl
CMFCProperySheetListBox
CMFCRibbonBar
CMFCRibbonPanelMenuBar
CMFCRibbonRichEditCtrl
CMFCSpinButtonCtrl
CMFCToolBar
ReplaceThisTextCMFCToolBarComboBoxEdit
CMFCToolBarEditCtrl
CMFCAutoHideBar
Mengubah tanda tangan
OnPowerBroadcast
untuk setuju dengan makro ON_WM_POWERBROADCAST:CFrameWndEx
CMDIFrameWndEx
Mengubah tanda tangan
OnStyleChanged
untuk setuju dengan makro ON_WM_STYLECHANGED:CMFCListCtrl
CMFCStatusBar
Mengganti nama metode
FontFamalyProcFonts
internal menjadiFontFamilyProcFonts
.Menghapus banyak objek statis
CString
global untuk menghilangkan kebocoran memori dalam beberapa situasi (diganti dengan #defines), dan variabel anggota kelas berikut: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
Mengubah tanda tangan
CKeyboardManager::ShowAllAccelerators
dan menghapus parameter pemisah akselerator.Ditambahkan
CPropertyPage::GetParentSheet
, dan diCPropertyPage
kelas , panggil alih-alihGetParent
untuk mendapatkan jendela lembar induk yang benar, yang mungkin merupakan jendela induk atau kakek-nenek keCPropertyPage
. Anda mungkin harus mengubah kode Anda untuk memanggilGetParentSheet
alih-alihGetParent
.Memperbaiki peringatan #pragma yang tidak seimbang (push) di ATLBASE. H, yang menyebabkan peringatan dinonaktifkan dengan tidak benar. Peringatan tersebut sekarang diaktifkan dengan benar setelah ATLBASE. H telah diurai.
Memindahkan metode terkait D2D dari AFX_GLOBAL_DATA ke _AFX_D2D_STATE:
GetDirectD2dFactory
GetWriteFactory
GetWICFactory
InitD2D
ReleaseD2DRefs
IsD2DInitialized
D2D1MakeRotateMatrix
Alih-alih memanggil, misalnya, ,
afxGlobalData.IsD2DInitialized
panggilAfxGetD2DState->IsD2DInitialized
.
MENGHAPUS ATL usang*. File CPP dari folder \atlmfc\include\.
afxGlobalData
Memindahkan inisialisasi ke sesuai permintaan alih-alih pada waktu inisialisasi CRT, untuk memenuhiDLLMain
persyaratan.RemoveButtonByIndex
Menambahkan metode keCMFCOutlookBarPane
kelas .Dikoreksi
CMFCCmdUsageCount::IsFreqeuntlyUsedCmd
keIsFrequentlyUsedCmd
.Mengoreksi beberapa instans ke
RestoreOriginalstate
RestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane)
.Menghapus metode yang tidak digunakan dari
CDockablePane
: , ,IsDrawCaption
,IsHideDisabledButtons
GetRecentSiblingPaneInfo
, danCanAdjustLayout
SetCaptionStyle
.CDockablePane
Menghapus variabelm_bCaptionText
anggota statis danm_bHideDisabledButtons
.Menambahkan metode penimpaan
DeleteString
keCMFCFontComboBox
.Menghapus metode yang tidak digunakan dari
CPane
:GetMinLength
danIsLastPaneOnLastRow
.Diganti namanya
CPane::GetDockSiteRow(CDockingPanesRow *)
menjadiCPane::SetDockSiteRow
.
Perubahan Melanggar Visual Studio 2010
Kompilator
Kata
auto
kunci memiliki arti default baru. Karena penggunaan makna lama jarang terjadi, sebagian besar aplikasi tidak akan terpengaruh oleh perubahan ini.Kata kunci baru
static_assert
diperkenalkan, yang akan menyebabkan konflik nama jika sudah ada pengidentifikasi dengan nama tersebut dalam kode Anda.Dukungan untuk notasi lambda baru mengecualikan dukungan untuk pengkodean GUID yang tidak dikutip dalam atribut uuid IDL.
.NET Framework 4 memperkenalkan konsep pengecualian status yang rusak, yang merupakan pengecualian yang meninggalkan proses dalam keadaan rusak yang tidak dapat dipulihkan. Secara default, Anda tidak dapat menangkap pengecualian status yang rusak, bahkan dengan opsi pengkompilasi /EHa yang menangkap semua pengecualian lainnya. Untuk menangkap pengecualian status yang rusak secara eksplisit, gunakan pernyataan __except __try. Atau, terapkan atribut [HandledProcessCorruptedStateExceptions]untuk memungkinkan fungsi menangkap pengecualian status yang rusak. Perubahan ini terutama memengaruhi programmer sistem yang mungkin harus menangkap pengecualian status yang rusak. Delapan pengecualian tersebut adalah 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. Untuk informasi selengkapnya tentang pengecualian ini, lihat makro GetExceptionCode .
Opsi kompilator yang direvisi
/GS
melindungi dari overruns buffer secara lebih komprehensif daripada pada versi sebelumnya. Versi ini mungkin menyisipkan pemeriksaan keamanan tambahan di tumpukan yang mungkin mengurangi performa. Gunakan kata kunci baru__declspec(safebuffers)
untuk menginstruksikan pengkompilasi untuk tidak menyisipkan pemeriksaan keamanan untuk fungsi tertentu.Jika Anda mengkompilasi dengan
/GL
opsi/GL
pengkompilasi (Pengoptimalan Seluruh Program) dan/clr
(Kompilasi Runtime Bahasa Umum), opsi akan diabaikan. Perubahan ini dilakukan karena kombinasi opsi pengkompilasi memberikan sedikit manfaat. Akibat perubahan ini, performa build ditingkatkan.Secara default, dukungan untuk trigraf dinonaktifkan di Visual Studio 2010.
/Zc:trigraphs
Gunakan opsi pengkompilasi untuk mengaktifkan dukungan trigraf. Trigraf terdiri dari dua tanda tanya berturut-turut ("??") diikuti oleh karakter ketiga yang unik. Pengkompilasi menggantikan trigraf dengan karakter tanda baca yang sesuai. Misalnya, pengkompilasi menggantikan??=
trigraf dengan karakter '#'. Gunakan trigraf dalam file sumber C yang menggunakan kumpulan karakter yang tidak berisi representasi grafik yang nyaman untuk beberapa karakter tanda baca.Linker tidak lagi mendukung pengoptimalan untuk Windows 98. Opsi
/OPT
(Pengoptimalan) menghasilkan kesalahan waktu kompilasi jika Anda menentukan/OPT:WIN98
atau/OPT:NOWIN98
.Opsi kompilator default yang ditentukan oleh properti sistem build RuntimeLibrary dan DebugInformationFormat telah diubah. Secara default, properti build ini ditentukan dalam proyek yang dibuat oleh Rilis Visual C++ 7.0 hingga 10.0. Jika Anda memigrasikan proyek yang dibuat oleh Visual C++ 6.0, pertimbangkan apakah akan menentukan nilai untuk properti ini.
Di Visual Studio 2010, RuntimeLibrary = MultiThreaded (
/MD
) dan DebugInformationFormat = ProgramDatabase (/Zi
). Di Visual C++ 9.0, RuntimeLibrary = MultiThreaded (/MT
) dan DebugInformationFormat = Disabled.
CLR
- Pengkompilasi Microsoft C# dan Visual Basic sekarang dapat menghasilkan perakitan interop utama (tanpa PIA). Rakitan no-PIA dapat menggunakan jenis COM tanpa penyebaran perakitan interop utama (PIA) yang relevan. Saat menggunakan rakitan no-PIA yang dihasilkan oleh Visual C# atau Visual Basic, Anda harus mereferensikan rakitan PIA pada perintah kompilasi sebelum Mereferensikan rakitan tanpa PIA yang menggunakan pustaka.
Proyek Visual Studio C++ dan MSBuild
Proyek Visual Studio C++ sekarang didasarkan pada alat MSBuild. Akibatnya, file proyek menggunakan format file XML baru dan akhiran file .vcxproj. Visual Studio 2010 secara otomatis mengonversi file proyek dari versi Visual Studio yang lebih lama ke format file baru. Proyek yang ada terpengaruh jika bergantung pada alat build sebelumnya, VCBUILD.exe, atau akhiran file proyek, .vcproj.
Dalam rilis sebelumnya, Visual C++ mendukung evaluasi lembar properti yang terlambat. Misalnya, lembar properti induk dapat mengimpor lembar properti anak, dan induk dapat menggunakan variabel yang ditentukan dalam anak untuk menentukan variabel lain. Evaluasi terlambat memungkinkan induk untuk menggunakan variabel anak bahkan sebelum lembar properti anak diimpor. Di Visual Studio 2010, variabel lembar proyek tidak dapat digunakan sebelum ditentukan karena MSBuild hanya mendukung evaluasi awal.
IDE
Kotak dialog penghentian aplikasi tidak lagi mengakhiri aplikasi. Dalam rilis sebelumnya, ketika
abort()
fungsi atauterminate()
menutup build ritel aplikasi, Pustaka Run-Time C menampilkan pesan penghentian aplikasi di jendela konsol atau kotak dialog. Pesan tersebut mengatakan sebagian, "Aplikasi ini telah meminta Runtime untuk mengakhirinya dengan cara yang tidak biasa. Silakan hubungi tim dukungan aplikasi untuk informasi lebih lanjut." Pesan penghentian aplikasi berlebihan karena Windows kemudian menampilkan handler penghentian saat ini, yang biasanya merupakan kotak dialog Pelaporan Galat Windows (Dr. Watson) atau debugger Visual Studio. Mulai dari Visual Studio 2010, Pustaka Run-Time C tidak menampilkan pesan. Selain itu, runtime mencegah aplikasi berakhir sebelum debugger dimulai. Ini adalah perubahan yang melanggar hanya jika Anda bergantung pada perilaku sebelumnya dari pesan penghentian aplikasi.Khusus untuk Visual Studio 2010, IntelliSense tidak berfungsi untuk kode atau atribut C++/CLI, Temukan Semua Referensi tidak berfungsi untuk variabel lokal, dan Model Kode tidak mengambil nama jenis dari rakitan yang diimpor atau mengatasi jenis ke nama yang sepenuhnya memenuhi syarat.
Pustaka
Kelas SafeInt disertakan dalam Visual C++ dan tidak lagi dalam unduhan terpisah. Ini adalah perubahan yang melanggar hanya jika Anda telah mengembangkan kelas yang juga bernama "SafeInt".
Model penyebaran pustaka tidak lagi menggunakan manifes untuk menemukan versi tertentu dari pustaka tautan dinamis. Sebagai gantinya, nama setiap pustaka tautan dinamis berisi nomor versinya, dan Anda menggunakan nama tersebut untuk menemukan pustaka.
Di versi Visual Studio sebelumnya, Anda dapat membangun kembali pustaka run time. Visual Studio 2010 tidak lagi mendukung pembuatan salinan file pustaka run time C Anda sendiri.
Pustaka Standar
Header
<iterator>
tidak lagi disertakan secara otomatis oleh banyak file header lainnya. Sebagai gantinya, sertakan header tersebut secara eksplisit jika Anda memerlukan dukungan untuk iterator mandiri yang ditentukan di header. Proyek yang ada terpengaruh jika bergantung pada alat build sebelumnya, VCBUILD.exe, atau akhiran file proyek, .vcproj.iterator.<algorithm>
Di header,checked_*
fungsi danunchecked_*
dihapus. Dan di<iterator>
> header,checked_iterator
kelas dihapus, danunchecked_array_iterator
kelas telah ditambahkan.CComPtr::CComPtr(int)
Konstruktor dihapus. Konstruktor itu memungkinkanCComPtr
objek dibangun dari makro NULL, tetapi tidak perlu dan diizinkan konstruksi nonsensik dari bilangan bulat bukan nol.masih
CComPtr
dapat dibangun dari NULL, yang didefinisikan sebagai 0, tetapi akan gagal jika dibangun dari bilangan bulat selain literal 0. Gunakannullptr
sebagai gantinya.Fungsi anggota berikut
ctype
dihapus:ctype::_Do_narrow_s
, ,ctype::_Do_widen_s
ctype::_narrow_s
,ctype::_widen_s
. Jika aplikasi menggunakan salah satu fungsi anggota ini, Anda harus menggantinya dengan versi yang tidak aman yang sesuai:ctype::do_narrow
, ,ctype::do_widen
ctype::narrow
,ctype::widen
.
Pustaka CRT, MFC, dan ATL
Dukungan telah dihapus bagi pengguna untuk membangun pustaka CRT, MFC, dan ATL. Misalnya, tidak ada file NMAKE yang sesuai yang disediakan. Namun, pengguna masih memiliki akses ke kode sumber untuk pustaka ini. Dan dokumen yang menjelaskan opsi MSBuild yang digunakan Microsoft untuk membangun pustaka ini mungkin akan diposting di Blog Tim Visual C++.
Dukungan MFC untuk IA64 telah dihapus. Namun, dukungan untuk CRT dan ATL pada IA64 masih disediakan.
Ordinal tidak lagi digunakan kembali dalam file module-definition (.def) MFC. Perubahan ini berarti ordinal tidak akan berbeda antara versi minor, dan kompatibilitas biner untuk paket layanan dan rilis rekayasa perbaikan cepat akan ditingkatkan.
Fungsi virtual baru ditambahkan ke
CDocTemplate
kelas . Fungsi virtual baru ini adalah Kelas CDocTemplate. Versi sebelumnya memilikiOpenDocumentFile
dua parameter. Versi baru memiliki tiga parameter. Untuk mendukung manajer hidupkan ulang, kelas apa pun yang berasal dariCDocTemplate
harus mengimplementasikan versi yang memiliki tiga parameter. Parameter baru adalahbAddToMRU
.
Makro dan Variabel Lingkungan
- Variabel lingkungan __MSVCRT_HEAP_SELECT tidak lagi didukung. Variabel lingkungan ini dihapus dan tidak ada penggantian.
Referensi Perakitan Makro Microsoft
- Beberapa direktif dihapus dari pengkompilasi Referensi Perakitan Makro Microsoft. Direktif yang dihapus adalah
.186
, ,.286
,.287
.286P
,.8086
,.8087
, dan.NO87
.
Perubahan Yang Melanggar Visual Studio 2008
Kompilator
Platform Windows 95, Windows 98, Windows ME, dan Windows NT tidak lagi didukung. Sistem operasi ini telah dihapus dari daftar platform yang ditargetkan.
Pengkompilasi tidak lagi mendukung beberapa atribut yang terkait langsung dengan ATL Server. Atribut berikut tidak lagi didukung:
perf_counter
perf_object
perfmon
request_handler
soap_handler
soap_header
soap_method
tag_name
Proyek Visual Studio C++
Saat meningkatkan proyek dari versi Visual Studio sebelumnya, Anda mungkin harus memodifikasi makro WINVER dan _WIN32_WINNT sehingga lebih besar dari atau sama dengan 0x0500.
Dimulai dengan Visual Studio 2008, wizard proyek baru tidak memiliki opsi untuk membuat proyek C++ SQL Server. Proyek SQL Server yang dibuat dengan menggunakan versi Visual Studio yang lebih lama masih akan dikompilasi dan berfungsi dengan benar.
File header Windows API Winable.h telah dihapus. Sertakan Winuser.h sebagai gantinya.
Pustaka Windows API Rpcndr.lib telah dihapus. Tautkan dengan rpcrt4.lib sebagai gantinya.
CRT
Dukungan untuk Windows 95, Windows 98, Windows Millennium Edition, dan Windows NT 4.0 telah dihapus.
Variabel global berikut telah dihapus:
_osplatform
_osver
_winmajor
_winminor
_winver
Fungsi berikut telah dihapus. Gunakan fungsi
GetVersion
Windows API atauGetVersionEx
sebagai gantinya:_get_osplatform
_get_osver
_get_winmajor
_get_winminor
_get_winver
Sintaks untuk Anotasi SAL telah berubah. Untuk informasi selengkapnya, lihat Anotasi SAL.
Filter IEEE sekarang mendukung set instruksi SSE 4.1. Untuk informasi selengkapnya, lihat _fpieee_flt_fpieee_flt.
Pustaka Run-Time C yang dikirim dengan Visual Studio tidak lagi bergantung pada dll sistem msvcrt.dll.
Pustaka Standar
Dukungan untuk Windows 95, Windows 98, Windows Millennium Edition, dan Windows NT 4.0 telah dihapus.
Saat mengkompilasi dalam mode debug dengan _HAS_ITERATOR_DEBUGGING ditentukan (digantikan oleh _ITERATOR_DEBUG_LEVEL setelah Visual Studio 2010), aplikasi sekarang akan menegaskan ketika iterator mencoba untuk meningkatkan atau menurunkan melewati batas kontainer yang mendasar.
Variabel anggota c dari Kelas tumpukan sekarang dinyatakan dilindungi. Sebelumnya, variabel anggota ini dinyatakan publik.
Perilaku
money_get::do_get
telah berubah. Sebelumnya, ketika menguraikan jumlah moneter dengan lebih banyak digit pecahan daripada yang dipanggil olehfrac_digits
,do_get
digunakan untuk mengonsumsi semuanya. Sekarang,do_get
berhenti mengurai setelah mengkonsumsi sebagian besarfrac_digits
karakter.
ATL
ATL tidak dapat dibangun tanpa dependensi pada CRT. Di versi Visual Studio yang lebih lama, Anda dapat menggunakan #define ATL_MIN_CRT untuk membuat proyek ATL minimal bergantung pada CRT. Di Visual Studio 2008, semua proyek ATL minimal bergantung pada CRT terlepas dari apakah ATL_MIN_CRT ditentukan.
Basis kode ATL Server telah dirilis sebagai proyek sumber bersama di CodePlex dan tidak diinstal sebagai bagian dari Visual Studio. Kelas pengodean dan pendekodean data dari atlenc.h dan fungsi dan kelas utilitas dari atlutil.h dan atlpath.h telah disimpan dan sekarang menjadi bagian dari pustaka ATL. Beberapa file yang terkait dengan ATL Server tidak lagi menjadi bagian dari Visual Studio.
Beberapa fungsi tidak lagi disertakan dalam DLL. Mereka masih terletak di pustaka impor. Ini tidak akan memengaruhi kode yang menggunakan fungsi secara statis. Ini hanya akan memengaruhi kode yang menggunakan fungsi-fungsi ini secara dinamis.
Makro PROP_ENTRY dan PROP_ENTRY_EX tidak digunakan lagi dan diganti dengan makro PROP_ENTRY_TYPE dan PROP_ENTRY_TYPE_EX karena alasan keamanan.
Kelas Bersama ATL/MFC
ATL tidak dapat dibangun tanpa dependensi pada CRT. Di versi Visual Studio yang lebih lama, Anda dapat menggunakan
#define ATL_MIN_CRT
untuk membuat proyek ATL minimal bergantung pada CRT. Di Visual Studio 2008, semua proyek ATL minimal bergantung pada CRT terlepas dari apakah ATL_MIN_CRT ditentukan.Basis kode ATL Server telah dirilis sebagai proyek sumber bersama di CodePlex dan tidak diinstal sebagai bagian dari Visual Studio. Kelas pengodean dan pendekodean data dari atlenc.h dan fungsi dan kelas utilitas dari atlutil.h dan atlpath.h telah disimpan dan sekarang menjadi bagian dari pustaka ATL. Beberapa file yang terkait dengan ATL Server tidak lagi menjadi bagian dari Visual Studio.
Beberapa fungsi tidak lagi disertakan dalam DLL. Mereka masih terletak di pustaka impor. Ini tidak akan memengaruhi kode yang menggunakan fungsi secara statis. Ini hanya akan memengaruhi kode yang menggunakan fungsi-fungsi ini secara dinamis.
MFC
CTime
Kelas: KelasCTime
sekarang menerima tanggal mulai dari 1/1/1900 C.E. alih-alih 1/1/1970 C.E.Urutan tab kontrol dalam dialog MFC: Urutan tab yang benar dari beberapa kontrol dalam dialog MFC terganggu jika kontrol MFC ActiveX disisipkan dalam urutan tab. Perubahan ini memperbaiki masalah tersebut.
Misalnya, buat aplikasi dialog MFC yang memiliki kontrol ActiveX dan beberapa kontrol edit. Posisikan kontrol ActiveX di tengah urutan tab kontrol edit. Mulai aplikasi, klik kontrol edit yang urutan tabnya setelah kontrol ActiveX, lalu tab. Sebelum perubahan ini, fokus masuk ke kontrol edit mengikuti kontrol ActiveX alih-alih kontrol edit berikutnya dalam urutan tab.
CFileDialog
Kelas: Templat kustom untukCFileDialog
kelas tidak dapat secara otomatis di-port ke Windows Vista. Mereka masih dapat digunakan, tetapi tidak akan memiliki fungsionalitas tambahan atau tampilan dialog gaya Windows Vista.CWnd
Kelas danCFrameWnd
Kelas: MetodeCWnd::GetMenuBarInfo
dihapus.Metode ini
CFrameWnd::GetMenuBarInfo
sekarang menjadi metode non-virtual. Untuk informasi selengkapnya, lihat Fungsi GetMenuBarInfo di Windows SDK.Dukungan MFC ISAPI: MFC tidak lagi mendukung pembangunan aplikasi dengan Internet Server Application Programming Interface (ISAPI). Jika Anda ingin membangun aplikasi ISAPI, hubungi ekstensi ISAPI secara langsung.
API ANSI yang tidak digunakan lagi: Versi ANSI dari beberapa metode MFC tidak digunakan lagi. Gunakan versi Unicode dari metode tersebut di aplikasi Anda di masa mendatang. Untuk informasi selengkapnya, lihat Persyaratan Build untuk Kontrol Umum Windows Vista.
Perubahan Melanggar Visual Studio 2005
CRT
Banyak fungsi tidak digunakan lagi. Lihat Fungsi CRT yang tidak digunakan lagi.
Banyak fungsi sekarang memvalidasi parameternya, menghentikan eksekusi jika diberikan parameter yang tidak valid. Validasi ini dapat memutus kode yang melewati parameter yang tidak valid dan bergantung pada fungsi yang mengabaikannya atau hanya mengembalikan kode kesalahan. Lihat Validasi Parameter.
Nilai deskriptor file -2 sekarang digunakan untuk menunjukkan bahwa
stdout
danstderr
tidak tersedia untuk output, misalnya, dalam aplikasi Windows yang tidak memiliki jendela konsol. Nilai sebelumnya yang digunakan adalah -1. Untuk informasi selengkapnya, lihat _fileno.Pustaka CRT berulir tunggal (libc.lib dan libcd.lib) telah dihapus. Gunakan pustaka CRT multi-utas. Bendera
/ML
pengkompilasi tidak lagi didukung. Versi non-penguncian dari beberapa fungsi telah ditambahkan dalam kasus di mana perbedaan performa antara kode multithreaded dan kode utas tunggal berpotensi signifikan.Kelebihan pow, double pow(int, int), dihapus agar lebih sesuai dengan standar.
Penentu format %n tidak lagi didukung secara default dalam keluarga fungsi cetak karena secara inheren tidak aman. Jika %n ditemui, perilaku defaultnya adalah memanggil handler parameter yang tidak valid. Untuk mengaktifkan dukungan %n, gunakan
_set_printf_count_output
(juga lihat_get_printf_count_output
).sprintf
sekarang mencetak tanda negatif dari nol yang ditandatangani.swprintf
telah diubah agar sesuai dengan Standar; sekarang memerlukan parameter ukuran. Bentukswprintf
tanpa parameter ukuran telah ditolak._set_security_error_handler
telah dihapus. Hapus panggilan apa pun ke fungsi tersebut; handler default adalah cara yang jauh lebih aman untuk menangani kesalahan keamanan.time_t
sekarang adalah nilai 64-bit (kecuali _USE_32BIT_TIME_T ditentukan)._spawn
,_wspawn
Functions sekarang tidakerrno
tersentuh pada keberhasilan, seperti yang ditentukan oleh Standar C.RTC sekarang menggunakan karakter lebar secara default.
Fungsi dukungan kata kontrol floating-point tidak digunakan lagi untuk aplikasi yang dikompilasi dengan
/CLR
atau/CLR:PURE
. Fungsi yang terpengaruh adalah_clear87
, ,_clearfp
,_control87
_controlfp
,_fpreset
,_status87
,_statusfp
. Anda dapat menonaktifkan peringatan penghentian dengan mendefinisikan _CRT_MANAGED_FP_NO_DEPRECATE, tetapi penggunaan fungsi-fungsi ini dalam kode terkelola tidak dapat diprediksi dan tidak didukung.Beberapa fungsi sekarang mengembalikan penunjuk const. Perilaku lama dan non-const dapat dipulihkan dengan menentukan _CONST_RETURN. Fungsi yang terpengaruh adalah
memchr, wmemchr
strchr, wcschr, _mbschr, _mbschr_l
strpbrk, wcspbrk, _mbspbrk, _mbspbrk_l
strrchr, wcsrchr, _mbsrchr, _mbsrchr_l
strstr, wcsstr, _mbsstr, _mbsstr_l
Saat menautkan dengan Setargv.obj atau Wsetargv.obj, tidak mungkin lagi untuk menekan ekspansi karakter kartubebas pada baris perintah dengan mengapitnya dalam tanda kutip ganda. Untuk informasi selengkapnya, lihat Memperluas Argumen Wildcard.
Pustaka Standar (2005)
Kelas pengecualian (terletak di
<exception>
header) telah dipindahkan kestd
namespace layanan. Di versi sebelumnya, kelas ini berada di namespace layanan global. Untuk mengatasi kesalahan yang menunjukkan bahwa kelas pengecualian tidak dapat ditemukan, tambahkan pernyataan penggunaan berikut ke kode Anda:using namespace std;
Saat memanggil
valarray::resize()
, kontenvalarray
akan hilang dan akan digantikan oleh nilai default. Metoderesize()
ini dimaksudkan untuk menginisialisasi ulangvalarray
daripada menumbuhkannya secara dinamis seperti vektor.Debug Iterator: Aplikasi yang dibangun dengan versi debug pustaka C-Runtime dan yang menggunakan iterator mungkin mulai melihat pernyataan pada runtime. Untuk menonaktifkan pernyataan ini, Anda harus menentukan _HAS_ITERATOR_DEBUGGING (digantikan setelah
_ITERATOR_DEBUG_LEVEL
Visual Studio 2010) menjadi 0. Untuk informasi selengkapnya, lihat Debug Dukungan Iterator
Perubahan Pemecahan Visual C++ .NET 2003
Kompilator
Menutup tanda kurung sekarang diperlukan untuk arahan praprosesor yang ditentukan (C2004).
Spesialisasi eksplisit tidak lagi menemukan parameter templat dari templat utama (Compiler Error C2146).
Anggota yang dilindungi (n) hanya dapat diakses melalui fungsi anggota kelas (B) yang mewarisi dari kelas (A) di mana itu (n) adalah anggota (Compiler Error C2247).
Peningkatan pemeriksaan aksesibilitas di kompilator sekarang mendeteksi kelas dasar yang tidak dapat diakses (Compiler Error C2248).
Pengecualian tidak dapat ditangkap jika konstruktor destruktor dan/atau salinan tidak dapat diakses (C2316).
Argumen default pada pointer ke fungsi tidak lagi diizinkan (Compiler Error C2383).
Anggota data statis tidak dapat diinisialisasi melalui kelas turunan (Compiler Error C2477).
Inisialisasi
typedef
a tidak diizinkan oleh standar dan sekarang menghasilkan kesalahan kompilator (Compiler Error C2513).bool
sekarang merupakan jenis yang tepat (Compiler Error C2632).UDC sekarang dapat menciptakan ambiguitas dengan operator yang kelebihan beban (C2666).
Ekspresi lainnya sekarang dianggap sebagai konstanta pointer null yang valid (Compiler Error C2668).
templat<> sekarang diperlukan di tempat-tempat di mana pengkompilasi sebelumnya akan menyiratkannya (Compiler Error C2768).
Spesialisasi eksplisit dari fungsi anggota di luar kelas tidak valid jika fungsi telah dikhususkan secara eksplisit melalui spesialisasi kelas templat (Compiler Error C2910).
Parameter templat non-jenis titik mengambang tidak lagi diizinkan (Compiler Error C2993).
Templat kelas tidak diizinkan sebagai argumen jenis templat (C3206).
Nama fungsi Teman tidak lagi diperkenalkan dalam berisi namespace (Compiler Error C3767).
Pengkompilasi tidak akan lagi menerima koma tambahan dalam makro (C4002).
Objek jenis POD yang dibangun dengan inisialisasi formulir () akan diinisialisasi secara default (C4345).
typename sekarang diperlukan jika nama dependen akan diperlakukan sebagai jenis (Compiler Warning (tingkat 1) C4346).
Fungsi yang salah dianggap sebagai spesialisasi templat tidak lagi dipertimbangkan demikian (C4347).
Anggota data statis tidak dapat diinisialisasi melalui kelas turunan (C4356).
Spesialisasi templat kelas perlu ditentukan sebelum digunakan dalam jenis pengembalian (Compiler Warning (level 3) C4686).
Pengkompilasi sekarang melaporkan kode yang tidak dapat dijangkau (C4702).