Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini menjelaskan semua perubahan signifikan dari Visual Studio 2015 hingga Visual Studio 2003, dan dalam artikel ini istilah "perilaku baru" atau "sekarang" merujuk ke Visual Studio 2015 dan versi setelahnya. 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 merusak, dan biasanya diperlukan oleh modifikasi dalam standar bahasa C++, signature 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 Melintasi Objek CRT Lintas 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 Kepatuhan Visual Studio 2015
Pustaka Runtime C (CRT)
Perubahan Umum
Binaries yang sudah 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 ke Abaikan Semua Pustaka Default menjadi Ya atau Anda menggunakan opsi
/NODEFAULTLIBpada baris perintah, maka Anda harus memperbarui daftar pustaka Anda (dalam properti Dependensi Tambahan) untuk menyertakan pustaka baru yang telah diubah. Ganti pustaka CRT lama (libcmt.lib,libcmtd.lib,msvcrt.lib,msvcrtd.lib) dengan pustaka yang direfaktor 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 perlu 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.libversi vcruntime.dll,libvcruntimed.lib, dan versi vcruntimed.dll. Versi di Visual Studio 2015 dan Visual Studio 2017 adalah 140. Lihat Pustaka CRT - Fitur.
<locale.h>
localeconvFungsi
localeconvyang dideklarasikan dalam locale.h sekarang berfungsi dengan benar ketika lokal per utas diaktifkan. Di versi pustaka sebelumnya, fungsi ini akan mengembalikan datalconvuntuk wilayah global, bukan wilayah utas.Jika Anda menggunakan lokalisasi per utas, Anda harus memeriksa penggunaan Anda
localeconv. Jika kode Anda mengasumsikan bahwa data yanglconvdikembalikan 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) -
floatdanlong doubleversi fungsi titik mengambangacos,acosh,asin,asinh,atan,atanh,atan2,cbrt,ceil,copysign,cos,cosh,erf,erfc,exp,exp2,expm1,fabs,fdim,floor,fma,fmax,fmin,fmod,frexp,hypot,ilogb,ldexp,lgamma,llrint,llround,log,log10,log1p,log2,lrint,lround,modf,nearbyint,nextafter,nexttoward,remainder,remquo,rint,round,scalbln,scalbn,sin,sinh,sqrt,tan,tanh,tgamma, dantrunc
Jika Anda memiliki kode yang menggunakan
absdengan jenis bilangan titik mengambang yang hanya menyertakan header<math.h>, versi bilangan titik mengambang tidak akan tersedia lagi. Panggilan sekarang dialihkan keabs(int), bahkan ketika menggunakan argumen floating point, yang menghasilkan kesalahan:warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of dataPerbaikan untuk peringatan ini adalah mengganti panggilan ke
absdengan versi titik mengambang dariabs, sepertifabsuntuk argumen ganda ataufabsfuntuk argumen float, atau menyertakan<cmath>header dan terus menggunakanabs.-
Kesuaian titik mengambang
Banyak perubahan pada pustaka matematika telah dilakukan untuk meningkatkan ketaatan terhadap spesifikasi IEEE-754 dan C11 Annex F sehubungan dengan input kasus khusus seperti NaN dan infinitas. 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 kini bersifat dinamis dan secara akurat mencerminkan mode pembulatan yang sedang digunakan.
<new> dan <new.h>
newdandeleteDalam versi pustaka sebelumnya, fungsi operator 'new' dan 'delete' yang didefinisikan implementasi diekspor dari DLL pustaka runtime (contohnya, msvcr120.dll). Fungsi operator ini sekarang selalu ditautkan secara statis ke dalam biner Anda, bahkan saat menggunakan pustaka runtime DLL.
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:puretidak digunakan lagi di Visual Studio 2015 dan tidak didukung di Visual Studio 2017. Kode yang perlu "murni" harus di-port ke C#.
<process.h>
_beginthreaddan_beginthreadexFungsi
_beginthreaddan_beginthreadexsekarang menyimpan referensi ke modul tempat prosedur utas didefinisikan selama durasi utas. Ini membantu memastikan bahwa modul tidak dibongkar hingga utas berjalan sepenuhnya selesai.
<stdarg.h>
va_startdan jenis referensiSaat mengkompilasi kode C++,
va_startsekarang 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 printf dan scanf sekarang didefinisikan secara inline.
Definisi semua fungsi
printfdanscanftelah dipindahkan sebaris ke dalam<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.libke 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 Linker Input untuk menambahkan
legacy_stdio_definitions.libke daftar yang dipisahkan titik koma.Ketika proyek Anda ditautkan dengan pustaka statis yang dikompilasi dengan rilis Visual Studio sebelum 2015, linker mungkin melaporkan simbol eksternal yang tak terpecahkan. Kesalahan ini mungkin mereferensikan definisi internal untuk
_iob, ,_iob_funcatau 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.exeuntuk memeriksa simbol yang ditentukan dalam biner. Coba baris perintah berikut untuk melihat simbol yang ditentukan dalam pustaka.dumpbin.exe /LINKERMEMBER somelibrary.libgets 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 gets tetapi untuk string bertipe lebar. Sebagai alternatif untuk fungsi-fungsi ini, pertimbangkan penggunaan fgets, fgetws, 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 tidak terdefinisi: 1.#IND
Salah satu format ini mungkin telah diawali oleh tanda dan mungkin telah diformat sedikit berbeda tergantung pada lebar kolom dan ketelitian (kadang-kadang dengan efek yang tidak biasa, misalnya
printf("%.2f\n", INFINITY)akan mencetak 1.#J karena #INF akan "dibulatkan" ke ketelitian 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 Tentu: nan(ind)
Salah satu mana pun dari ini dapat diawali dengan suatu tanda. Jika penentu format kapital digunakan (%F alih-alih %f), maka string dicetak dalam huruf kapital (
INFbukaninf), seperti yang diperlukan.Fungsi scanf telah dimodifikasi untuk mengurai string baru ini, sehingga string ini sekarang dapat dikirim dan diterima kembali melalui
printfdanscanf.Pemformatan dan penguraian floating point
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:
1208925819614629200000000Output baru:
1208925819614629174706176Algoritma 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 mengikuti mode pembulatan (yang dapat dikontrol melalui fesetround). Ini berpotensi menjadi perubahan yang mengganggu fungsi karena fungsi-fungsi ini bisa menghasilkan output berbeda. Hasil baru selalu lebih benar daripada hasil lama.
Penguraian titik float heksadesimal dan tak terbatas/NaN
Algoritma penguraian floating point sekarang akan mengurai string floating point heksadesimal (seperti yang dihasilkan oleh spesifikasi format printf %a dan %A) serta semua string Infinity dan NaN yang dihasilkan oleh fungsi
printf, seperti yang dijelaskan di atas.%A dan %a pengisian nol
Penentu format %a dan %A memformat angka titik mengambang sebagai mantissa heksadesimal dan eksponen biner. Dalam versi sebelumnya, fungsi
printfakan salah menambahkan nol di awal string. 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 untuk penentu format %A dan %a adalah 6 pada versi pustaka yang 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
Pengidentifikasi spesifikasi format/konversi %F 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 berasal dari era ruang alamat tersegmentasi: pengubah panjang ini digunakan untuk menunjukkan penunjuk jauh dan dekat, seperti pada %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 bentuk ini dalam beberapa keadaan. 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 format string
Dalam versi sebelumnya,
printffungsi danscanfakan 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,
fopenkeluarga fungsi secara diam-diam menerima beberapa string mode yang tidak valid, sepertir+b+. String mode tidak valid kini terdeteksi dan dianggap sebagai parameter yang tidak valid.modus _O_U8TEXT
Fungsi _setmode sekarang melaporkan dengan benar mode untuk stream yang dibuka dalam mode in_O_U8TEXT. Di versi pustaka sebelumnya, pustaka akan melaporkan stream tersebut sebagai dibuka di _O_WTEXT.
Ini adalah perubahan mendasar jika kode Anda menginterpretasikan mode _O_WTEXT untuk stream 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
snprintfatauvsnprintfdalam kode pengguna.tmpnam Menghasilkan Nama File yang Dapat Digunakan
Dalam versi sebelumnya,
tmpnamfungsi dantmpnam_smenghasilkan 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. Perpustakaan telah diubah untuk menyembunyikan detail implementasi. Sebagai bagian dari perubahan ini, FILE seperti yang didefinisikan dalam<stdio.h>sekarang adalah tipe opak 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
strtofdanwcstofgagal mengaturerrnoke ERANGE ketika nilai tidak dapat diwakili sebagai float. Kesalahan ini khusus untuk kedua fungsi ini;strtodfungsi ,wcstod,strtold, danwcstoldtidak terpengaruh. Masalah ini telah diperbaiki, dan mengakibatkan perubahan yang mempengaruhi waktu proses.Fungsi alokasi yang diselaraskan
Dalam versi sebelumnya, fungsi alokasi yang selaras (
_aligned_malloc, ,_aligned_offset_mallocdll.) akan secara diam-diam menerima permintaan untuk blok dengan penyelarasan 0. Perataan yang diminta harus berupa pangkat dua, yang tidak berlaku untuk nol. Penyelarasan 0 yang diminta sekarang diperlakukan sebagai parameter yang tidak valid. Masalah ini telah diperbaiki, dan merupakan perubahan yang mempengaruhi kompatibilitas runtime.Fungsi timbunan
Fungsi
_heapadd,_heapset, dan_heapusedtelah dihapus. Fungsi-fungsi ini tidak berfungsi setelah CRT diperbarui untuk menggunakan heap Windows.tumpukan kecil
Opsi
smallheaptautan telah dihapus. Lihat Opsi Tautan._stat
Fungsi keluarga
_statmenggunakanCreateFiledi Visual Studio 2015, alih-alihFindFirstFileseperti di Visual Studio 2013 dan sebelumnya. Ini berarti bahwa pada jalur yang diakhiri dengan garis miring berhasil jika jalur tersebut mengacu pada direktori, berbeda dengan sebelumnya ketika fungsi akan mengalami kesalahan denganerrnodiatur keENOENT.
<string.h>
wcstokIntisari dari fungsi
wcstoktelah diubah untuk memenuhi persyaratan dari Standar C. Di versi pustaka sebelumnya, tanda tangan fungsi ini adalah:wchar_t* wcstok(wchar_t*, wchar_t const*)Ini menggunakan konteks internal setiap 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
_wcstoktelah ditambahkan dengan tanda tangan lama untuk memudahkan porting. Saat mengompilasi kode C++, terdapat juga 'overload' inline dariwcstokyang memiliki 'signature' lama. Kelebihan beban ini dinyatakan tidak digunakan lagi. Dalam kode C, Anda dapat define_CRT_NON_CONFORMING_WCSTOK menyebabkan_wcstokdigunakan sebagai penggantiwcstok.
<time.h>
jam
Di versi sebelumnya,
clockfungsi diimplementasikan menggunakan Windows APIGetSystemTimeAsFileTime. Dengan implementasi ini, fungsi jam sensitif terhadap waktu sistem, dan dengan demikian tidak selalu monoton. Fungsi jam telah diimplementasikan ulang menggunakanQueryPerformanceCounterdan sekarang bersifat monotonik.fstat dan _utime
Dalam versi sebelumnya,
_statfungsi , ,fstatdan_utimesalah 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
_statkeluarga fungsi, tetapi masalah serupa dalamfstatkeluarga fungsi dan_utimetidak diperbaiki. Perbaikan parsial ini menyebabkan masalah karena ketidakkonsistensian antara fungsi. Keluarga fungsifstatdan_utimetelah diperbaiki, sehingga semua fungsi ini sekarang menangani waktu musim panas dengan benar dan konsisten.asktime
Dalam versi sebelumnya, fungsi
asctimeakan mengisi hari dengan satu digit dengan nol di depannya, misalnya:Fri Jun 06 08:00:00 2014. Spesifikasi mengharuskan hari tersebut disertakan dengan spasi di depan, seperti dalamFri Jun 6 08:00:00 2014. Masalah ini telah diperbaiki.strftime dan wcsftime
Fungsi
strftimedanwcsftimesekarang 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, pengformatan waktu dengan spesifikasi format %c salah menggunakan representasiMM/DD/YY HH:MM:SS. Masalah ini telah diperbaiki.timespec dan TIME_UTC
Header
<time.h>sekarang menentukan tipetimespecdan fungsitimespec_getdari Standar C11. Selain itu, makro TIME_UTC, untuk digunakan dengan fungsitimespec_get, sekarang didefinisikan. Pembaruan ini adalah perubahan signifikan 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 optimasi dan pemeriksaan debug baru, implementasi Pustaka Standar C++ di Visual Studio sengaja merusak kompatibilitas biner antara versi. 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 menghasilkan kesalahan linker mengenai 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::arraytanpa 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_clocktelah berubah untuk memenuhi persyaratan Standar C++ untuk ketepatan dan monotonisitas.steady_clocksekarang didasarkan padaQueryPerformanceCounterdanhigh_resolution_clocksekarang menjadi typedef untuksteady_clock. Akibatnya, di Visual Studiosteady_clock::time_pointsekarang menjadi typedef untukchrono::time_point<steady_clock>; namun, ini belum tentu terjadi untuk implementasi lain.pengalokasi 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 konstanta:
bool operator==(const MyAlloc& other) constelemen 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::deallocate
Di Visual Studio 2013 dan versi sebelumnya,
std::allocator::deallocate(p, n)mengabaikan argumen yang diteruskan untuk n. Standar C++ selalu mengharuskan bahwa n harus sama dengan nilai yang telah diteruskan sebagai argumen pertama dalam pemanggilanallocate, yang mengembalikan p. Namun, dalam versi saat ini, nilai n diperiksa. Kode yang meneruskan argumen untuk n yang berbeda dari apa yang diperlukan menurut standar mungkin mengalami kerusakan saat waktu jalan.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) constjenis 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 tambahkan referensi tambah_referensi_lvalue memiliki_konstruktor_default dapat_dikonstruksi_default memiliki_konstruktor_salinan dapat_dibuat_melalui_penyalinan memiliki_konstruktor_pemindahan bisa_dikonstruksi_dengan_pemindahan memiliki konstruktor tanpa lemparan dapat_dibangun_kembali_secara_default_tanpa_lemparan memiliki_konstruktor_default_tanpa_throw dapat_dibangun_kembali_secara_default_tanpa_lemparan has_nothrow_copy is_nothrow_copy_constructible (apakah dapat dikonstruksi tanpa pengecualian) mempunyai_konstruktor_salinan_tanpa_lemparan is_nothrow_copy_constructible (apakah dapat dikonstruksi tanpa pengecualian) Mempunyai_konstruktor_pindah_tanpa_lemparan is_nothrow_move_constructible memiliki_penugasan_tanpa_lemparan is_nothrow_copy_assignable memiliki_penugasan_salinan_tanpa_pengecualian is_nothrow_copy_assignable has_nothrow_move_assign is_nothrow_move_assignable memiliki_konstruktor_sepele dapat_dikonstruksi_dengan_caraterbiasa_bawaan memiliki_konstruktor_default_Sepele dapat_dikonstruksi_dengan_caraterbiasa_bawaan memiliki_salinan_sepele bersifat_konstruktif_salinan_trivial has_trivial_move_constructor (memiliki konstruktor pemindahan sederhana) adalah_konstruksi_pindah_secara_trivial memiliki_penugasan_sepele is_trivially_copy_assignable (dapat ditetapkan salin secara sepele) memiliki_pengalihan_sepele dapat_dipindahkan_trivial_ditugaskan memiliki_destruktor_sepele dapat_dihancurkan_dengan_mudah launch::any dan launch::sync kebijakan
Kebijakan nonstandard
launch::anydanlaunch::syncdihapus. Sebagai gantinya, untuklaunch::any, gunakanlaunch:async | launch:deferred. Untuklaunch::sync, gunakanlaunch::deferred. Lihat launch Enumeration.
MFC dan ATL
Kelas Microsoft Foundation (MFC)
tidak lagi disertakan dalam penginstalan Standar Visual Studio karena ukuran 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 pengaturan Visual Studio dari Panel Kontrol di Program dan Fitur, atau dari media penginstalan.
Paket Visual C++ Redistributable masih menyertakan pustaka ini.
Runtime Konkurensi
Makro Yield dari Windows.h berbenturan dengan concurrency::Context::Yield
Runtime Konkruensi sebelumnya menggunakan
#undefuntuk membatalkan definisi makro Yield guna menghindari konflik antara makro Yield yang ditentukan dalam Windows.h h dan fungsiconcurrency::Context::Yield. Ini#undeftelah dihapus dan panggilan API setara baru yang tidak bertentangan concurrency::Context::YieldExecution telah ditambahkan. Untuk mengatasi konflik dengan Yield, Anda dapat memperbarui kode untuk memanggilYieldExecutionfungsi sebagai gantinya, atau mengelilingiYieldnama 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 sederhana. 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 memutus lebih parah, dan dapat memengaruhi kompatibilitas biner, tetapi pemutusan kompatibilitas biner seperti 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 releaseBiasanya, 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 opsi
/Za, karena tanpa/Za, penggunaan variabel perulangan setelah loop selesai selalu diizinkan. Jika Anda tidak peduli tentang kesuaian standar (misalnya, jika kode Anda tidak dimaksudkan untuk portabel ke pengkompilasi lain), Anda dapat menonaktifkan/Zaopsi (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 }/Zgopsi pengkompilasiOpsi
/Zgpengkompilasi (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 opsi VSTest.Console.exe baris perintah.
kata kunci yang dapat diubah
Penentu
mutablekelas penyimpanan tidak lagi diizinkan di tempat-tempat di mana sebelumnya dikompilasi tanpa kesalahan. Sekarang, kompilator memberikan kesalahan C2071 (kelas penyimpanan ilegal). Menurut standar, penentumutablehanya 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 classUntuk memperbaiki kesalahan, hapus kata kunci redundan
mutable.char_16_t dan char32_t
Anda tidak dapat lagi menggunakan
char16_tatauchar32_tsebagai alias dalamtypedef, karena jenis ini sekarang diperlakukan sebagai bawaan. Biasanya pengguna dan penulis pustaka mendefinisikanchar16_tdanchar32_tsebagai alias dariuint16_tdanuint32_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 deklarasi
typedefdan ganti nama pengidentifikasi lain yang bertabrakan dengan nama-nama ini.Parameter templat non-jenis
Kode tertentu yang melibatkan parameter templat non-tipe sekarang diperiksa untuk kompatibilitas tipe dengan benar 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>(); }Kompilator saat ini memberikan kesalahan dengan tepat, karena jenis parameter templat tidak sesuai dengan argumen templat (parameter adalah pointer ke anggota yang bersifat const, tetapi fungsi f bersifat 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)pada fungsi. Konstruksi ini selalu diabaikan, tetapi sekarang menghasilkan kesalahan kompilator.error C3323: 'alignas' and '__declspec(align)' are not allowed on function declarationsUntuk 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 penyalin bersifat privat, sehingga objek tidak dapat disalin seperti yang biasanya dilakukan dalam penanganan 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
publicdan 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
catchmenjadi referensi.catch (D& d) { }Literal string 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 literal yang didefinisikan pengguna, tetapi karena tidak ada literal yang sesuai yang didefinisikan pengguna
_x, pengkompilasi menghasilkan 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 yang digabungkan tunggal dalam rilis Visual 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
deleteoperator agar sesuai dengan standar C++14. Detail perubahan standar dapat ditemukan di Pembebasan Memori dengan Ukuran C++. Perubahan menambahkan bentuk operator globaldeleteyang mengambil parameter ukuran. Perubahan yang memutus adalah jika sebelumnya Anda menggunakan operatordeletedengan tanda tangan yang sama (untuk menyesuaikan dengan operator placement new), Anda akan menerima kesalahan kompilator (C2956, yang terjadi pada titik di mana placement new digunakan, karena itulah posisi dalam kode di mana pengkompilasi mencoba mengidentifikasi operatordeleteyang sesuai).Fungsi
void operator delete(void *, size_t)adalah operator placement delete yang sesuai dengan fungsi placement newvoid * operator new(size_t, size_t)di C++11. Dengan ukuran dealokasi C++14, fungsi penghapusan ini sekarang merupakan fungsi dealokasi pada umumnya (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 placement new dan placement delete:
void * operator new(std::size_t, std::size_t); void operator delete(void*, std::size_t) noexcept;Masalah terjadi karena kecocokan tanda tangan fungsi antara operator "placement delete" yang telah Anda tentukan, dan operator berskala global yang baru. Pertimbangkan apakah Anda dapat menggunakan jenis yang berbeda selain
size_tuntuk "placement new" dandeleteoperator. Tipe darisize_ttypedefbergantung pada compiler; ini adalahtypedefuntukunsigned intdalam MSVC. Solusi yang baik adalah menggunakan jenis enumerasi seperti ini:enum class my_type : size_t {};Kemudian, ubah definisi placement new dan
deleteuntuk menggunakan jenis ini sebagai argumen kedua alih-alihsize_t. Anda juga harus memperbarui panggilan ke placement new untuk meneruskan jenis baru (misalnya, dengan menggunakanstatic_cast<my_type>untuk mengonversi dari nilai bilangan bulat) dan memperbarui definisinewdandeleteuntuk mengonversi kembali ke jenis bilangan bulat. Anda tidak perlu menggunakanenumuntuk ini; sebuah kelas dengan anggotasize_tjuga 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
deleteAnda 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 hapus dengan dua argumen tidak ada dan tidak akan menyebabkan konflik dengan operator penempatan hapus Anda.Anggota data union
Anggota data dari union tidak dapat lagi memiliki tipe 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 typeUntuk 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, hal ini juga dapat mengubah ukuran union.
Serikat anonim sekarang lebih sesuai dengan standar. Versi kompilator sebelumnya menghasilkan konstruktor dan destruktor eksplisit untuk union anonim. Fungsi yang dihasilkan kompilator ini dihapus di Visual Studio 2015.
struct S { S(); }; union { struct { S s; }; } u; // C2280Kode 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>' hereUntuk 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 calledUntuk 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 dalam fungsi baru, dan tambahkan panggilan ke fungsi-fungsi ini dari konstruktor dan destruktor untuk union.
#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 saat pemanggilan pertama is_base_of, kelas
Dbelum didefinisikan.Dalam hal ini, perbaikannya adalah tidak menggunakan sifat jenis tersebut sampai kelas telah ditentukan. Jika Anda memindahkan definisi
BdanDke 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.Konstruktor penyalin
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".
Fungsi main yang dideklarasikan sebagai ekstern "C" sekarang memerlukan tipe pengembalian.
Kode berikut sekarang menghasilkan C4430.
extern "C" __cdecl main(){} // C4430Untuk memperbaiki kesalahan, tambahkan jenis pengembalian:
extern "C" int __cdecl main(){} // OKtypename tidak diizinkan dalam inisialisasi 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
typenamedari 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_assertselalu gagal:template <size_t some_value> struct S1 { static_assert(false, "default not valid"); // always invoked }; //other partial specializations hereUntuk 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 hereAturan yang diterapkan untuk deklarasi ke depan. (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 identifierUntuk memperbaiki masalah ini, tambahkan deklarasi maju 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 denganusingdeklarasi sebagai gantinya.Pola ini sering terjadi dengan ComPtr dan jenis lainnya di dalam namespace
Microsoft::WRL.Perbaiki alamat yang salah dari
Kode berikut sekarang menghasilkan C2440: '=': tidak dapat mengonversi dari 'type *' ke 'type'. Untuk memperbaiki kesalahan, ubah &(type) 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 larik konstan
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 isihagar terlihat seperti contoh ini:void h(void) { char name[] = __FUNCTION__; f( name); void *p = &""; }UDL string C++11
1. Kode berikut sekarang menghasilkan kesalahan C3688: akhiran literal 'L' yang tidak valid; operator literal atau template operator literal '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,
MACROtidak lagi diurai sebagai dua token (string diikuti oleh makro). Sekarang UDL diproses sebagai 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'; }Eksepsi MFC tidak dapat ditangkap melalui nilai karena tidak dapat disalin
Kode berikut dalam aplikasi MFC sekarang menyebabkan kesalahan C2316: 'D': tidak dapat ditangkap karena destruktor dan/atau konstruktor 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.alignofsekarang 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{}constexprsekarang 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;}Tipe bergerak 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); //C2280Untuk memperbaiki kesalahan, gunakan inisialisasi langsung untuk
S2:struct S{ S(int, int); S(const S&) = delete; S(S&&) = delete; }; S s2 = {2,3}; //OKKonversi 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 tangkapan.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
S2diS: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 dapat diubah menjadi penunjuk fungsi.
Lambdas dengan operator penyisipan 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::movesebagai 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, pindahkan definisi
S2ke posisi lebih atas.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
S2panggilan 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
0atau gunakannullptrsebagai 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: tipe 'int' tidak terduga
#define A (int) struct S { A a; };Untuk memperbaiki masalah, tentukan
Aseperti ini:#define A intKurung tambahan dalam deklarasi
Kode berikut menghasilkan kesalahan C2062: tipe 'int' tidak diharapkan
struct S { int i; (int)j; };Untuk memperbaiki kesalahan, hapus tanda kurung di sekitar
j. Jika tanda kurung diperlukan untuk kejelasan, maka gunakantypedef.Konstruktor yang dihasilkan kompilator dan __declspec(novtable)
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).auto memerlukan ekspresi tunggal dalam direct-list-initialization
Kode berikut sekarang menghasilkan kesalahan C3518: 'testPositions': dalam konteks inisialisasi-daftar langsung, tipe data 'auto' hanya dapat disimpulkan dari satu ekspresi penginisialisasi.
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
testPositionssebagai 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 tipe vs. pointer ke tipe 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_assertsehingga membandingkan pointer denganDdanB2:static_assert(std::is_convertible<D*, B2*>::value, "fail");deklarasi __declspec(dapat diubah) harus konsisten
__declspecdeklarasi harus konsisten di semua perpustakaan. 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 virtualtidak 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 functionContoh (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 sebelumnya dari kompilator memungkinkan non-anggota operator new dan non-anggota operator delete untuk dinyatakan sebagai statis, dan dideklarasikan dalam namespace selain namespace global. Perilaku lama ini menciptakan risiko bahwa program tidak akan memanggil operator atau implementasi
newdandeleteyang diinginkan oleh programmer, yang dapat menghasilkan masalah runtime yang tidak terlihat. 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 C2323Contoh (setelah)
void * __cdecl operator new(size_t cb, const std::nothrow_t&) // removed 'static inline'Selain itu, meskipun kompilator tidak memberikan pesan diagnostik tertentu, operator sebaris
newdianggap salah bentuk.Memanggil 'operator type()' (konversi yang ditentukan pengguna) pada tipe 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/unionContoh (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 spesifikasi jenis yang dijabarkan
Versi kompilator sebelumnya mengizinkan
typenamedalam spesifikasi tipe yang terelaborasi, tetapi kode yang ditulis dengan cara ini salah secara semantik. 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 specifierContoh (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;Penentuan tipe 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
switchpernyataan; 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 peringatan tersebut yang sekarang dikeluarkan pada baris yang berbeda dibandingkan sebelumnya, peringatan yang sebelumnya dihilangkan dengan menggunakan#pragma warning(disable:####)mungkin tidak lagi dihilangkan seperti yang dimaksudkan. Untuk menekan peringatan ini seperti yang dimaksudkan, mungkin perlu untuk memindahkan#pragma warning(disable:####)direktif ke baris di atas kasus pertama yang menyebabkan peringatan. Berikut ini adalah peringatan yang dipulihkan:warning C4060: switch statement contains no 'case' or 'default' labelswarning C4061: enumerator 'bit1' in switch of enum 'flags' is not explicitly handled by a case labelwarning C4062: enumerator 'bit1' in switch of enum 'flags' is not handledwarning C4063: case 'bit32' is not a valid value for switch of enum 'flags'warning C4064: switch of incomplete enum 'flags'warning C4065: switch statement contains 'default' but no 'case' labelswarning C4808: case 'value' is not a valid value for switch condition of type 'bool'Warning C4809: switch statement has redundant 'default' label; all possible 'case' labels are givenContoh 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 spesifikator direktori utama '..' 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 C4464Contoh (setelah)
#include "C4426.h" // add absolute path to 'headers\' to your project's include directoriesSelain itu, meskipun pengkompilasi tidak memberikan diagnosa tertentu, kami juga menyarankan agar spesifikator direktori induk ".." tidak boleh digunakan untuk menentukan direktori penyertaan untuk proyek Anda.
#pragma optimize() melebihi akhir dari file header (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 flag optimasi yang diberikan pada pengompilasi melalui baris perintah.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 C4426Contoh (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"Ketidaksesuaian #pragma warning(push) dan #pragma warning(pop) (hanya memengaruhi
/Wall/WX)Versi kompilator sebelumnya tidak mendeteksi
#pragma warning(push)perubahan status yang dipasangkan dengan#pragma warning(pop)perubahan status di file sumber yang berbeda, yang jarang diinginkan. Perilaku lama ini menciptakan risiko bahwa program akan dikompilasi dengan serangkaian peringatan yang berbeda dari yang dimaksudkan oleh programmer, yang mungkin mengakibatkan terjadinya perilaku runtime yang buruk secara diam-diam. 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 fileContoh (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
#includesecara 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.hContoh (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 karena peningkatan pelacakan status peringatan pragma
Versi sebelumnya dari kompilator melacak perubahan status peringatan pragma dengan kurang efektif sehingga tidak semua peringatan yang dimaksud dapat dikeluarkan. Perilaku ini menimbulkan risiko bahwa peringatan tertentu akan secara efektif ditekan dalam keadaan yang berbeda dari yang diinginkan oleh programmer. Kompilator sekarang melacak
#pragma warningstatus dengan lebih kuat -- terutama terkait dengan perubahan#pragma warningdi 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 warningpelacakan 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++ mengalami perubahan dan peningkatan dalam kemampuan untuk memanggil fungsi secara sebaris dibandingkan dengan versi kompilator sebelumnya, yang mungkin memungkinkan pengkompilasi untuk membuktikan bahwa kode tertentu sekarang tidak dapat diakses. Perilaku baru ini dapat menghasilkan instans peringatan C4720 baru dan lebih sering dikeluarkan.
warning C4720: unreachable codeDalam 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 peringatan baru 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 spesifikasi
decltypekarena tidak adanya 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
decltypeekspresi 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 ekspresi
decltypeyang tidak memiliki penggunaan kata kuncitypenameyang diperlukan untuk menetapkan bahwa nama dependen adalah tipe, kompilator mengeluarkan peringatan C4346 bersamaan dengan kesalahan C2923.warning C4346: 'S2<T>::Type': dependent name is not a typeerror C2923: 's1': 'S2<T>::Type' is not a valid template type argument for parameter 'T'Contoh 2: nama bergantung bukan tipe (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> ())); };volatilevariabel anggota mencegah konstruktor dan operator penugasan yang ditentukan secara implisitVersi kompilator sebelumnya memungkinkan kelas yang memiliki
volatilevariabel 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 memilikivolatilevariabel 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 functionContoh (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 C2280Contoh (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 C2280Fungsi anggota statis tidak mendukung pengualifikasi 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 {} // C2511Contoh(setelah)
struct A { static void func(); }; void A::func() {} // removed constDeklarasi ke depan enum tidak diizinkan dalam kode WinRT (hanya mempengaruhi
/ZW)Kode yang dikompilasi untuk Windows Runtime (WinRT) tidak memungkinkan jenis
enumuntuk dideklarasikan terlebih dahulu, mirip dengan ketika kode C++ terkelola dikompilasi untuk .Net Framework menggunakan opsi pengompilasi/clr. 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 allowederror C3197: 'public': can only be used in definitionsContoh (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 terstruktur dengan baik (tanpa membutuhkan diagnostik) dan dapat menyebabkan masalah memori yang diakibatkan oleh operator new dan delete yang tidak cocok (terutama ketika digunakan bersama dengan dealokasi dengan ukuran) yang sulit untuk 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 inlineContoh (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_convertible sekarang mendeteksi penugasan diri sendiri (pustaka standar)
Versi sebelumnya dari
std::is_convertabletype-trait tidak mendeteksi penetapan sendiri jenis kelas dengan benar saat konstruktor salinannya dihapus atau privat. Sekarang,std::is_convertable<>::valuedikonfigurasi dengan benar menjadifalsesaat diterapkan ke tipe kelas dengan konstruktor salinan privat atau yang dihapus.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<>::valuesalah diatur ketrue. Sekarang,std::is_convertable<>::valuediatur dengan benar kefalse, menyebabkan asersi statis gagal.Konstruktor salinan trivial atau pindah yang diatur ulang atau dihapus menghormati penentu akses
Versi kompilator sebelumnya tidak memeriksa penentu akses dari konstruktor salinan dan pemindahan sepele yang di-default-kan atau dihapus sebelum mengizinkan pemanggilan mereka. 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. Pengompilasi sekarang memeriksa penentu akses dari konstruktor penyalinan sepele yang dijadikan default atau dihapus dan konstruktor pemindahan untuk menentukan apakah 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 untuk kode ATL yang diatribusikan (Tingkat 1 (
/W1) secara default diaktifkan)Versi sebelumnya dari kompilator mendukung kode ATL yang memiliki atribut. Sebagai langkah berikutnya dalam menghapus dukungan untuk kode ATL atribut yang dimulai di Visual Studio 2008, kode ATL atribut tersebut telah dihentikan. Kompilator sekarang mengeluarkan peringatan kompilator C4467 untuk membantu mengidentifikasi jenis kode yang tidak digunakan lagi ini.
warning C4467: Usage of ATL attributes is deprecatedJika Anda ingin terus menggunakan kode ATL yang diatribusikan hingga dukungan dihapus dari pengkompilasi, Anda dapat menonaktifkan peringatan ini dengan meneruskan
/Wv:18argumen baris perintah atau/wd:4467ke 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
#includedalam file sumber antara-Ycdan-Yukompilasi 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#includesaat menggunakan file PCH.warning C4598: 'b.h': included header file specified for Ycc.h at position 2 does not match Yuc.h at that positionContoh (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"Header yang telah dikompilasi sebelumnya (PCH) dan direktori pencantuman yang tidak cocok (hanya memengaruhi
/Wall/WX)Versi kompilator sebelumnya yang diterima tidak cocok termasuk argumen baris perintah direktori (
-I) ke kompilator antara-Ycdan-Yukompilasi 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 positionContoh (sebelumnya)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h Z.cppContoh (setelah)
cl /c /Wall /Ycc.h -I.. X.cpp cl /c /Wall /Yuc.h -I.. Z.cpp
Perubahan Kesesuaian Standar Visual Studio 2013
Kompilator
Kata kunci final sekarang menghasilkan kesalahan simbol yang tidak terselesaikan, padahal sebelumnya dapat dikompilasi.
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 itu adalah panggilan
virtual; namun, program akan mengalami kerusakan saat waktu jalan. Sekarang, sebuah error linker terjadi 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
friendfungsi: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 kompilator sesuai dengan ISO C++11, kode berikut akan dikompilasi dan menyebabkan
xuntuk menyelesaikan sebagai tipeint.auto x = {0}; int y = x;Kode ini sekarang menyelesaikan
xmenjadi tipestd::initializer_list<int>dan menyebabkan kesalahan pada baris berikutnya yang mencoba menetapkanxke tipeint. (Tidak ada konversi secara default.) Untuk memperbaiki kode ini, gunakanintuntuk 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}; // errorUntuk 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; }Dalam Visual Studio 2012, ekspresi
E1diE1::bdiselesaikan menjadi::E1dalam cakupan global. Di Visual Studio 2013,E1dalam ekspresiE1::bmengacu pada definisitypedef E2dimain()dan bertipe::E2.Tata letak objek telah berubah. Pada x64, tata letak objek kelas dapat berubah dari rilis sebelumnya. Jika memiliki
virtualfungsi tetapi tidak memiliki kelas dasar yang memilikivirtualfungsi, model objek kompiler akan menyisipkan penunjuk kevirtualtabel 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 simbol
sizeof(S2)pada x64 adalah 48, tetapi dalam rilis sebelumnya, hasilnya dihasilkan menjadi 32. Untuk membuat ini mengevaluasi ke 32 di pengkompilasi Visual Studio 2013 C++ pada x64, tambahkan kelas dasar dummy yang memiliki sebuah fungsivirtual.__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 bersama dengan opsi kompilator
/W3dan 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>::typetidak 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::readymasih 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 dari kata kunci yang peka terhadap konteks seperti override dan final.
reference_wrapper,ref(), dancref()sekarang melarang pengikatan ke objek sementara.<random>sekarang secara ketat memberlakukan prasyarat waktu kompilasinya.Berbagai sifat tipe dari Pustaka Standar C++ memiliki prasyarat "T harus merupakan tipe yang 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, ini membuatcommon_type<int, int>::typemengembalikanint&&. Oleh karena itu, kompilator mengimplementasikan Resolusi Usulan untuk Masalah Kelompok Kerja Perpustakaan 2141, yang membuatcommon_type<int, int="">::typemengembalikanint.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 identitas jenis, jangan gunakan
std::identityyang tidak standar dan ditentukan dalam<type_traits>karena 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::GetConnectmetode 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::Dumpmetode .Tanda tangan dari
CWnd::OnPowerBroadcasttelah 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::OnDisplayChangediubah ke (UINT, int, int) alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_DISPLAYCHANGE baru dapat digunakan di peta pesan.CFrameWnd::OnDDEInitiatediubah ke (CWnd*, UINT, UNIT) alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_DDE_INITIATE baru dapat digunakan di peta pesan.CFrameWnd::OnDDEExecutediubah ke (CWnd*, HANDLE) alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_DDE_EXECUTE baru dapat digunakan di peta pesan.CFrameWnd::OnDDETerminatediubah menjadi (CWnd*) sebagai parameter, bukan (WPARAM, LPARAM), sehingga makro ON_WM_DDE_TERMINATE yang baru dapat digunakan dalam peta pesan.CMFCMaskedEdit::OnCutdiubah menjadi tanpa parameter alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_CUT baru dapat digunakan dalam peta pesan.CMFCMaskedEdit::OnCleardiubah menjadi tanpa parameter daripada (WPARAM, LPARAM) sehingga makro ON_WM_CLEAR baru dapat digunakan dalam peta pesan.CMFCMaskedEdit::OnPastediubah menjadi tanpa parameter alih-alih (WPARAM, LPARAM) sehingga makro ON_WM_PASTE yang baru dapat digunakan di message map.
#ifdefdirektif dalam file header MFC dihapus.#ifdefBanyak 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.
CTraceCategoryKonstruktor sekarang mengambil satu parameter (nama kategori), dan makro TRACE memanggil fungsi pelaporan debug CRT.
Perubahan Signifikan Visual Studio 2012
Kompilator
Opsi
/Ylpengkompilasi telah berubah. Secara default, pengkompilasi menggunakan opsi ini, yang dapat menyebabkan kesalahan LNK2011 dalam kondisi tertentu. Untuk informasi lebih lanjut, lihat /Yl (Suntikkan Referensi PCH untuk Perpustakaan Debug).Dalam kode yang dikompilasi dengan menggunakan
/clr,enumkata 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 Tipe yang Bergantung.
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
/GSopsi 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 terminateArsitektur 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:IA32bendera 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 parameter linker baru
/HIGHENTROPYVAditentukan, Windows 8 biasanya membuat 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
/HIGHENTROPYVAbuild terkelola. Namun, dalam hal ini,/HIGHENTROPYVAswitchnonaktif 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 Kesamaan
Enumerasi SchedulerTypeUmsThreadDefault tidak digunakan lagi. Spesifikasi UmsThreadDefault menghasilkan peringatan yang tidak digunakan lagi, dan secara internal memetakan kembali ke ThreadScheduler.
Pustaka Standar
Setelah perubahan signifikan antara standar C++98/03 dan C++11, penggunaan argumen templat secara eksplisit untuk memanggil
make_pair()— seperti dalammake_pair<int, int>(x, y)— biasanya tidak dapat dikompilasi di Visual C++ pada 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, gunakanpairalih-alihmake_pair— seperti dalampair<short, short>(int1, int2).Perubahan mendasar lainnya antara standar C++98/03 dan C++11: Ketika A dapat dikonversi secara implisit ke B dan B dapat dikonversi secara implisit ke C, tetapi A tidak dapat dikonversi secara implisit ke C, C++98/03 dan Visual Studio 2010 mengizinkan
pair<A, X>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 mempercepat waktu kompilasi dan mengurangi konsumsi memori kompilator bagi 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 menghasilkan kesalahan kompilator jika mendeteksi kata kunci yang telah diganti oleh makro. (Mendefinisikan _ALLOW_KEYWORD_MACROS memungkinkan kode tersebut untuk dikompilasi, tetapi kami sangat mencegah penggunaan tersebut.) Sebagai pengecualian, bentuk
newmakro 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 sesuai dengan apa yang dinyatakan oleh namanya.Untuk menerapkan berbagai pengoptimalan dan pemeriksaan debugging, 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 Visual Studio 2010 dengan yang dikompilasi dengan kompilator C++ di Visual Studio 2012, menghasilkan kesalahan linker tentang ketidakcocokan _MSC_VER, di mana _MSC_VER adalah makro yang berisi versi utama dari kompilator (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
/MTpengkompilasi (rilis statis),/MTd(debug statis),/MD(rilis dinamis), dan/MDd(debug dinamis) dicampur.operator<(),operator>(),operator<=(), danoperator>=()sebelumnya tersedia untuk keluarga kontainerstd::unordered_mapdanstdext::hash_map, meskipun implementasinya tidak berguna. Operator non-standar ini telah dihapus di Visual C++ di Visual Studio 2012. Selain itu, pelaksanaanoperator==()danoperator!=()untuk keluargastd::unordered_maptelah diperpanjang untuk mencakup keluargastdext::hash_map. (Kami menyarankan agar Anda menghindari penggunaanstdext::hash_mapkeluarga dalam kode baru.)C++11 22.4.1.4 [locale.codecvt] menentukan bahwa
codecvt::length()dancodecvt::do_length()harus menggunakan parameterstateT&yang dapat dimodifikasi, tetapi Visual Studio 2010 menggunakanconst stateT&. Pengkompilasi C++ di Visual Studio 2012 mengambilstateT&sesuai dengan standar. Perbedaan ini signifikan bagi siapa saja yang mencoba menggantikan fungsi virtualdo_length().
CRT
Heap Runtime C (CRT), yang digunakan untuk "new" dan malloc(), sekarang publik. 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
threadlocaleinfostructtelah 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 untuk Fusion telah dihapus (afxcomctl32.h); karena itu, semua metode yang didefinisikan dalam
<afxcomctl32.h>juga telah dihapus. File header<afxcomctl32.h>dan<afxcomctl32.inl>telah dihapus.Mengubah nama menjadi
CDockablePane::RemoveFromDefaultPaneDividierCDockablePane::RemoveFromDefaultPaneDivider.Mengubah tanda tangan
CFileDialog::SetDefExtuntuk menggunakan LPCTSTR; oleh karena itu, build Unicode terpengaruh.Kategori pelacakan ATL yang usang telah dihapus.
Mengubah tanda tangan
CBasePane::MoveWindowuntuk mengambilconst CRect.Mengubah tanda tangan
CMFCEditBrowseCtrl::EnableBrowseButton.Menghapus
m_fntTabsdanm_fntTabsBolddariCMFCBaseTabCtrl.Menambahkan parameter ke
CMFCRibbonStatusBarPanekonstruktor. (Ini adalah parameter default, sehingga tidak melanggar sumber.)Menambahkan parameter ke
CMFCRibbonCommandsListBoxkonstruktor. (Ini adalah parameter default, sehingga tidak melanggar sumber.)API
AFXTrackMousetelah dihapus (beserta proseur timer yang terkait). Gunakan API Win32TrackMouseEventsebagai gantinya.Menambahkan parameter ke
CFolderPickerDialogkonstruktor. (Ini adalah parameter default, sehingga tidak melanggar sumber.)CFileStatusukuran struktur berubah: Anggotam_attributeberubah dari BYTE ke DWORD (agar sesuai dengan nilai yang dikembalikan dariGetFileAttributes).CRichEditCtrldanCRichEditViewgunakan MSFTEDIT_CLASS (kontrol RichEdit 4.1) alih-alih RICHEDIT_CLASS (kontrol RichEdit 3.0) dalam build Unicode.Dihapus
AFX_GLOBAL_DATA::IsWindowsThemingDrawParentBackgroundkarena selalu TRUE pada Windows Vista, Windows 7, dan Windows 8.Dihapus
AFX_GLOBAL_DATA::IsWindowsLayerSupportAvailablekarena 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.Mengganti nama
AFX_GLOBAL_DATA::DwmIsCompositionEnabledmenjadiIsDwmCompositionEnableduntuk menghilangkan konflik nama.Mengubah pengidentifikasi untuk sejumlah timer internal MFC dan memindahkan definisi ke afxres.h (AFX_TIMER_ID_*).
Mengubah definisi
OnExitSizeMovemetode agar sesuai dengan makro ON_WM_EXITSIZEMOVE.CFrameWndExCMDIFrameWndExCPaneFrameWnd
Mengubah nama dan tanda tangan
OnDWMCompositionChangeduntuk setuju dengan makro ON_WM_DWMCOMPOSITIONCHANGED:CFrameWndExCMDIFrameWndExCPaneFrameWnd
Mengubah signature
OnMouseLeavemetode untuk sesuai dengan makro ON_WM_MOUSELEAVE:CMFCCaptionBarCMFCColorBarCMFCHeaderCtrlCMFCProperySheetListBoxCMFCRibbonBarCMFCRibbonPanelMenuBarCMFCRibbonRichEditCtrlCMFCSpinButtonCtrlCMFCToolBarGantiTeksIniCMFCToolBarComboBoxEditCMFCToolBarEditCtrlCMFCAutoHideBar
Mengubah tanda tangan
OnPowerBroadcastuntuk setuju dengan makro ON_WM_POWERBROADCAST:CFrameWndExCMDIFrameWndEx
Mengubah tanda tangan
OnStyleChangeduntuk setuju dengan makro ON_WM_STYLECHANGED:CMFCListCtrlCMFCStatusBar
Mengganti nama metode
FontFamalyProcFontsinternal menjadiFontFamilyProcFonts.Menghapus banyak objek statis
CStringglobal untuk menghilangkan kebocoran memori dalam beberapa situasi (diganti dengan #defines), dan variabel anggota kelas berikut:CKeyBoardManager::m_strDelimiterCMFCPropertyGridProperty::m_strFormatCharCMFCPropertyGridProperty::m_strFormatShortCMFCPropertyGridProperty::m_strFormatLongCMFCPropertyGridProperty::m_strFormatUShortCMFCPropertyGridProperty::m_strFormatULongCMFCPropertyGridProperty::m_strFormatFloatCMFCPropertyGridProperty::m_strFormatDoubleCMFCToolBarImages::m_strPngResTypeCMFCPropertyGridProperty::m_strFormat
Mengubah tanda tangan
CKeyboardManager::ShowAllAcceleratorsdan menghapus parameter pemisah akselerator.Ditambahkan
CPropertyPage::GetParentSheet, dan di kelasCPropertyPage, panggil alih-alihGetParentuntuk mendapatkan jendela lembar induk yang benar, yang mungkin merupakan jendela induk atau kakek keCPropertyPage. Anda mungkin harus mengubah kode Anda untuk memanggilGetParentSheetalih-alihGetParent.Memperbaiki ketidakseimbangan penggunaan #pragma warning(push) di ATLBASE.H, yang menyebabkan peringatan dinonaktifkan secara tidak semestinya. Peringatan tersebut sekarang diaktifkan dengan benar setelah ATLBASE.H diuraikan.
Memindahkan metode terkait D2D dari AFX_GLOBAL_DATA ke _AFX_D2D_STATE:
GetDirectD2dFactoryGetWriteFactoryGetWICFactoryInitD2DReleaseD2DRefsIsD2DInitializedD2D1MakeRotateMatrixAlih-alih memanggil, contohnya
afxGlobalData.IsD2DInitialized, panggilAfxGetD2DState->IsD2DInitialized.
Menghapus file-file ATL*.CPP usang dari folder \atlmfc\include\.
Memindahkan inisialisasi
afxGlobalDatake berdasarkan permintaan daripada pada waktu inisialisasi CRT, untuk memenuhi persyaratanDLLMain.Menambahkan metode
RemoveButtonByIndexke kelasCMFCOutlookBarPane.Telah dikoreksi
CMFCCmdUsageCount::IsFreqeuntlyUsedCmdkeIsFrequentlyUsedCmd.Mengoreksi beberapa instans dari
RestoreOriginalstatekeRestoreOriginalState (CMFCToolBar, CMFCMenuBar, CMFCOutlookBarPane).Menghapus metode yang tidak digunakan dari
CDockablePane: , ,SetCaptionStyle,IsDrawCaptionIsHideDisabledButtons, danGetRecentSiblingPaneInfoCanAdjustLayout.Menghapus variabel anggota statis
CDockablePane,m_bCaptionText, danm_bHideDisabledButtons.Menambahkan metode penimpaan
DeleteStringkeCMFCFontComboBox.Menghapus metode yang tidak digunakan dari
CPane:GetMinLengthdanIsLastPaneOnLastRow.Diganti namanya
CPane::GetDockSiteRow(CDockingPanesRow *)menjadiCPane::SetDockSiteRow.
Perubahan Melanggar Visual Studio 2010
Kompilator
Kata
autokunci memiliki arti default baru. Karena penggunaan makna lama jarang terjadi, sebagian besar aplikasi tidak akan terpengaruh oleh perubahan ini.Kata kunci baru
static_assertdiperkenalkan, yang akan menyebabkan konflik nama jika sudah ada pengidentifikasi dengan nama tersebut dalam kode Anda.Dukungan untuk notasi lambda baru tidak mencakup dukungan untuk penggunaan GUID tanpa tanda kutip dalam atribut IDL 'uuid'.
.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 rusak secara eksplisit, gunakan pernyataan __try-__except. Atau, terapkan atribut [HandledProcessCorruptedStateExceptions]untuk memungkinkan fungsi menangkap pengecualian status yang rusak. Perubahan ini terutama berdampak pada pemrogram sistem yang mungkin harus menangkap pengecualian keadaan 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
/GSmelindungi 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 opsi pengkompilasi
/GL(Optimisasi Program Keseluruhan) dan/clr(Kompilasi Runtime Bahasa Umum), opsi/GLakan 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:trigraphsGunakan 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:WIN98atau/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 = Dinonaktifkan.
CLR (Common Language Runtime)
- Pengkompilasi Microsoft C# dan Visual Basic sekarang dapat menghasilkan tanpa perakitan interop utama (tanpa PIA). Rakitan tanpa-PIA dapat menggunakan tipe-tipe COM tanpa harus menyebarkan Primary Interop Assembly (PIA) yang relevan. Saat menggunakan assembly no-PIA yang dihasilkan oleh Visual C# atau Visual Basic, Anda harus mereferensikan assembly PIA pada perintah kompilasi sebelum mereferensikan assembly no-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 tertunda lembar properti. 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 fungsi
abort()atau fungsiterminate()menutup versi ritel dari aplikasi, Pustaka C Runtime menampilkan pesan penghentian aplikasi di jendela konsol atau sekotak pesan di 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 signifikan hanya jika Anda bergantung pada perilaku pesan penghentian aplikasi sebelumnya.Khusus untuk Visual Studio 2010, IntelliSense tidak bekerja untuk kode atau atribut C++/CLI, Temukan Semua Referensi tidak berfungsi untuk variabel lokal, dan Model Kode tidak mengambil kembali nama jenis dari rakitan yang diimpor atau mengurai jenis menjadi nama lengkap yang 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.Di header
<algorithm>, fungsichecked_*danunchecked_*dihapus. Dan di<iterator>> header,checked_iteratorkelas dihapus, danunchecked_array_iteratorkelas telah ditambahkan.CComPtr::CComPtr(int)konstruktor dihapus. Konstruktor tersebut memungkinkan objekCComPtrdibangun dari makro NULL, tetapi tidak perlu dan mengizinkan konstruksi yang tidak masuk akal dari bilangan bulat bukan nol.CComPtrmasih dapat dibangun dari NULL, yang didefinisikan sebagai 0, tetapi akan gagal jika dibangun dari bilangan bulat yang bukan 0 literal. Gunakannullptrsebagai gantinya.Fungsi anggota berikut
ctypedihapus:ctype::_Do_narrow_s, ,ctype::_Do_widen_sctype::_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_widenctype::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.
Nomor urut tidak lagi digunakan kembali dalam file modul-definisi (.def) MFC. Perubahan ini berarti urutan ordinal tidak akan berbeda antara versi minor, dan kompatibilitas biner untuk paket layanan serta rilis rekayasa perbaikan cepat akan ditingkatkan.
Fungsi virtual baru ditambahkan ke
CDocTemplatekelas . Fungsi virtual baru ini adalah CDocTemplate Class. Versi sebelumnya dariOpenDocumentFilememiliki dua parameter. Versi baru memiliki tiga parameter. Untuk mendukung manajer hidupkan ulang, kelas apa pun yang berasal dariCDocTemplateharus 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,.286P.287,.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:
penghitung_kinerja
perf_object
perfmon
pengelola permintaan
penangan sabun
soap_header
metode_soap
nama_tag
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, pengatur 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
GetVersionWindows API atauGetVersionExsebagai 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.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_gettelah berubah. Sebelumnya, ketika menguraikan jumlah moneter dengan lebih banyak digit pecahan daripada yang dipanggil olehfrac_digits,do_getakan mengonsumsi semuanya. Sekarang,do_getberhenti mengurai setelah memproses paling banyakfrac_digitskarakter.
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_CRTuntuk 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
CTimeKelas: KelasCTimesekarang 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.
CFileDialogKelas: Templat kustom untukCFileDialogkelas 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.CWndKelas danCFrameWndKelas: MetodeCWnd::GetMenuBarInfodihapus.Metode ini
CFrameWnd::GetMenuBarInfosekarang 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 menyebabkan kerusakan pada kode yang melewati parameter tidak valid dan bergantung pada fungsi untuk mengabaikannya atau sekadar mengembalikan kode kesalahan. Lihat Validasi Parameter.
Nilai deskriptor file -2 sekarang digunakan untuk menunjukkan bahwa
stdoutdanstderrtidak 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. Flag
/MLpengkompilasi tidak lagi didukung. Versi non-penguncian dari beberapa fungsi telah ditambahkan dalam kasus di mana perbedaan performa antara kode multi-utas dan kode utas tunggal berpotensi signifikan.Varian kelebihan fungsi pow, yaitu 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).sprintfsekarang mencetak tanda negatif dari nol bertanda.swprintftelah diubah agar sesuai dengan Standar; sekarang memerlukan parameter ukuran. Bentukswprintftanpa parameter ukuran telah ditolak._set_security_error_handlertelah dihapus. Hapus panggilan apa pun ke fungsi tersebut; handler default adalah cara yang jauh lebih aman untuk menangani kesalahan keamanan.time_tsekarang adalah nilai 64-bit (kecuali _USE_32BIT_TIME_T ditetapkan)._spawn,_wspawnFunctions sekarang tidak menyentuherrnoketika berhasil, sesuai Standar C.RTC sekarang menggunakan karakter lebar secara default.
Fungsi dukungan kata kontrol floating-point tidak digunakan lagi untuk aplikasi yang dikompilasi dengan
/CLRatau/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 pointer konstan. 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 ke ruang namastd. Di versi sebelumnya, kelas ini berada di namespace 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(), kontenvalarrayakan hilang dan akan digantikan oleh nilai default. Metoderesize()ini dimaksudkan untuk menginisialisasi ulangvalarraydaripada menumbuhkannya secara dinamis seperti vektor.Iterator Debug: Aplikasi yang dibangun dengan versi debug pustaka C-Runtime dan yang menggunakan iterator secara tidak benar mungkin mulai melihat assert selama runtime. Untuk menonaktifkan asersi ini, Anda harus menentukan _HAS_ITERATOR_DEBUGGING (yang digantikan oleh
_ITERATOR_DEBUG_LEVELsetelah Visual Studio 2010) menjadi 0. Untuk informasi selengkapnya, lihat Dukungan Pengerjaan Iterator
Perubahan Signifikan Visual C++ .NET 2003
Kompilator
Penutupan tanda kurung sekarang diwajibkan untuk direktif 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 destruktor dan/atau konstruktor penyalin 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
typedeftidak diizinkan oleh standar dan sekarang menyebabkan kesalahan kompilasi (Compiler Error C2513).boolsekarang 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 friend tidak lagi diperkenalkan dalam namespace yang memuat (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).