Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Visual Studio'da (MSVC) Microsoft C/C++ her sürümde uyumluluk iyileştirmeleri ve hata düzeltmeleri yapar. Bu makalede, ana sürüme ve sonra sürüme göre yapılan önemli iyileştirmeler listelenmiştir. Belirli bir sürümdeki değişikliklere doğrudan atlamak için, bu makalenin üst kısmındaki Bu makaledeki bağlantıları kullanın.
Bu belgede Visual Studio 2022'deki değişiklikler listelenir.
Visual Studio'nun önceki sürümlerindeki değişiklikler için:
Sürüm | Uyumluluk geliştirmeleri bağlantısı |
---|---|
2019 | Visual Studio 2019'da C++ uyumluluğu geliştirmeleri |
2017 | Visual Studio 2017’deki C++ uyumluluk geliştirmeleri |
2003-2015 | Visual C++ 2003 ile 2015 Arasındaki Farklar |
Visual Studio 2022 sürüm 17.14'te uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.14, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Uyumluluk geliştirmeleri
- Standart kitaplık sağlamlaştırma (P3471R4), standart kitaplıktaki bazı tanımsız davranış örneklerini __fastfail çağrısına dönüştürür. Varsayılan olarak kapalı. Proje genelinde etkinleştirmek için
_MSVC_STL_HARDENING=1
tanımlayın.
Gelişmiş davranış
- Kullanımdan sonra yapılan hataları azaltmak için "yok edici mezar taşları" uygulandı. Varsayılan olarak kapalı. Proje genelinde etkinleştirmek için
_MSVC_STL_DESTRUCTOR_TOMBSTONES=1
tanımlayın.
Hata düzeltmeleri
CUDA projesinde
<format>
kullanılırken oluşan hatalı derleyici hataları düzeltildi.Derleme sırasında yerel bir değişkenin adresinin istemeden açığa çıkabileceği bir sorunu düzelttik. Örneğin:
const unsigned & func() { const int x = 0; constexpr const unsigned & r1 = x; // Previously accepted, now an error return r1; } auto r = func(); // Previously, the local address leaked
Örnek #2
#include <initializer_list> void test() { constexpr std::initializer_list<int> xs { 1, 2, 3 }; // Previously accepted, now an error static constexpr std::initializer_list<int> ys { 1, 2, 3 }; // Correct usage - note use of static }
/permissive-
ile derlenen kod, artık bir bildirgedefriend
vestatic
birleşimini kabul etmemektedir. Genellikle düzeltme,static
'yu bildirimden kaldırmaktır. Örneğin:struct S { friend static void f(); // Previously accepted, now emits error C2440: 'static' cannot be used with 'friend' };
Geçici nitelikli türlere referans bağlama, temel veya türetilmiş bir sınıfa başvuru yapıldığında düzeltildi. Örneğin:
struct A {}; struct B : public A {}; void f(A&); // 1 void f(const volatile A&); // 2 f(B{}); // Previously called 2. This is ill-formed under /permissive- or /Zc:referenceBinding. Chooses 1 if relaxed reference binding rules are enabled.
Uyumluluk değişiklikleri, hata düzeltmeleri ve performans geliştirmeleri de dahil olmak üzere Standart Şablon Kitaplığı'nda yapılan değişikliklerin ayrıntılı bir özeti için bkz. STL Changelog VS 2022 17.14.
Visual Studio 2022 sürüm 17.13'te uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.13, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Uyumluluk değişiklikleri, hata düzeltmeleri ve performans geliştirmeleri dahil olmak üzere Standart Şablon Kitaplığı'nda yapılan değişikliklerin ayrıntılı bir özeti için bkz. STL Changelog VS 2022 17.13.
Argümana bağlı arama (ADL)
Dil yapıları, range-for ve yapılandırılmış bağlamalar gibi, begin
, end
veya get
gibi belirli tanımlayıcılar için bağımsız değişkene bağlı özel arama kurallarına sahiptir. Daha önce bu arama, bağımsız değişkene bağımlı arama için normalde ilişkili ad alanları kümesine dahil olmasa bile std
ad alanındaki adayları std
ad alanına dahil ediyordu.
Bu yapılar için std
bildirimleri getiren programlar artık derlenmez. Bunun yerine, bildirimlerin söz konusu türler (büyük olasılıkla genel ad alanı dahil) için normal bir ilişkili ad alanında olması gerekir.
template <typename T>
struct Foo {};
namespace std
{
// To correct the program, move these declarations from std to the global namespace
template <typename T>
T* begin(Foo<T>& f);
template <typename T>
T* end(Foo<T>& f);
}
void f(Foo<int> foo)
{
for (auto x : foo) // Previously compiled. Now emits error C3312: no callable 'begin' function found for type 'Foo<int>'
{
...
}
}
Uygulama tarafından ayrılmış makroları değiştiremezsiniz
Daha önce, derleyici _MSC_EXTENSIONS
gibi uygulama tarafından sağlanan bazı makroları değiştirmeye veya tanımlamayı kaldırmaya izin verdi. Belirli makroların tanımını değiştirmek tanımsız davranışa neden olabilir.
Bazı ayrılmış makro adlarını değiştirmeye veya tanımlarını kaldırmaya çalışmak artık birinci seviye uyarı C5308
ile sonuçlanacak.
/permissive-
modunda bu uyarı hata olarak değerlendirilir.
#undef _MSC_EXTENSIONS // Warning C5308: Modifying reserved macro name `_MSC_EXTENSIONS` may cause undefined behavior
Visual Studio 2022 sürüm 17.12'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.12, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Uyumluluk değişiklikleri, hata düzeltmeleri ve performans geliştirmeleri de dahil olmak üzere Standart Şablon Kitaplığı'nda yapılan değişikliklerin ayrıntılı bir özeti için bkz . STL Changelog VS 2022 17.12.
_com_ptr_t::operator bool()
artık açık
Bu, kaynak veya ikili düzeyde uyumsuzluğa neden olan bir değişikliktir.
bool
örneklerinden _com_ptr_t
'ye yapılan örtük dönüşümler şaşırtıcı olabilir veya derleyici hatalarına yol açabilir.
C.164: C++ Çekirdek Yönergelerinde örtük dönüştürme işleçlerinden kaçının ve bu kapsamda örtük dönüştürme işlevleri de önerilmez. Ve _com_ptr_t
, hem bool
hem de Interface*
için örtük dönüştürmeler içeriyordu. Bu iki örtük dönüştürme belirsizliğe yol açabilir.
Bu sorunu çözmek için bool
dönüştürme işlemi artık belirgin. Dönüştürme Interface*
de değişiklik yok.
Bu yeni davranışı geri çevirmek ve önceki örtük dönüştürmeyi geri yüklemek için bir makro sağlanır. Bu değişiklikten vazgeçmek için /D_COM_DISABLE_EXPLICIT_OPERATOR_BOOL
ile derleyin. Kodu örtük dönüştürmelere bağlı olmayacak şekilde değiştirmenizi öneririz.
Örneğin:
#include <comip.h>
template<class Iface>
using _com_ptr = _com_ptr_t<_com_IIID<Iface, &__uuidof(Iface)>>;
int main()
{
_com_ptr<IUnknown> unk;
if (unk) // Still valid
{
// ...
}
bool b = unk; // Still valid.
int v = unk; // Previously permitted, now emits C2240: cannot convert from '_com_ptr_t<_com_IIID<IUnknown,& _GUID_00000000_0000_0000_c000_000000000046>>' to 'int'
}
Sabit ifadeler artık her zaman noexcept
izin verme modunda değil
Bu, kaynak veya ikili düzeyde uyumsuzluğa neden olan bir değişikliktir.
Sabit bir ifade, bir hata fırlatabilme ihtimali olan bir özel durum belirtimiyle bildirilmiş bir fonksiyona işlev çağrısını içerse bile her zaman noexcept
kalırdı. Bu ifade C++17'de kaldırıldı, ancak Microsoft Visual C++ derleyicisi bunu tüm C++ dil sürümlerinde modda desteklemeye devam etti /permissive
.
Bu /permissive
mod davranışı kaldırıldı. Sabit ifadelere artık özel örtük davranışlar verilmez.
noexcept
İşlevlerdeki constexpr
tanımlayıcıya artık tüm modlarda uyuldu. Bu değişiklik, standart noexcept
davranışı kullanan sonraki temel sorun çözümlerinin doğru uygulanması için gereklidir.
Örneğin:
constexpr int f(bool b) noexcept(false)
{
if (b)
{
throw 1;
}
else
{
return 1;
}
}
void g(bool b)
{
noexcept(f(b)); // false. No change to behavior
noexcept(f(true)); // false. No change to behavior
noexcept(f(false)); // false. Was true in /permissive mode only in previous versions.
}
Visual Studio 2022 sürüm 17.11'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.11, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Uyumluluk değişiklikleri, hata düzeltmeleri ve performans geliştirmeleri de dahil olmak üzere Standart Şablon Kitaplığı'nda yapılan değişikliklerin ayrıntılı bir özeti için bkz . STL Changelog VS 2022 17.11.
Boş satırları yazdırmak için println
kullanın
P3142R0'e göre, artık ile boş bir satır oluşturmak kolaydır. Bu özellik /std:c++latest
ile derlenirken kullanılabilir.
Bu değişiklik öncesinde şunu yazdınız: println("");
Şimdi şunu yazacaksınız: println();
.
-
println();
eşdeğerdirprintln(stdout);
-
println(FILE* stream);
eşdeğerdirprintln(stream, "\n");
Uygulanan range_formatter
P2286R8 uyarınca range_formatter
artık uygulandı. Bu özellik /std:c++latest
ile derlenirken kullanılabilir.
Visual Studio 2022 sürüm 17.10'da uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.10, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Uyumluluk değişiklikleri, hata düzeltmeleri ve performans geliştirmeleri de dahil olmak üzere Standart Şablon Kitaplığı'nda yapılan değişikliklerin ayrıntılı bir özeti için bkz . STL Changelog VS 2022 17.10.
Açıkça belirtilen dönüş türüyle dönüştürme işleci özelleştirmesi
Bazı durumlarda dönüştürme işleçlerini yanlış özelleştirmek için kullanılan derleyici, eşleşmeyen bir dönüş türüne yol açabilir. Bu geçersiz özelleştirmeler artık gerçekleşmez. Bu, kaynak kodunun işleyişinde aksamalara neden olan bir değişikliktir.
// Example 1
struct S
{
template<typename T> operator const T*();
};
void test()
{
S{}.operator int*(); // this is invalid now
S{}.operator const int*(); // this is valid
}
// Example 2
// In some cases, the overload resolution result may change
struct S
{
template <typename T> operator T*(); // overload 1
template <typename T> operator const T*(); // overload 2
};
void test()
{
S{}.operator int*(); // this used to call overload 2, now it calls overload 1
}
#elifdef
ve #elifndef
için destek eklendi
WG21 P2334R1 (C++23) ve WG14 N2645 (C++23) ile tanıtılan #elifdef
ve #elifndef
ön işlemci yönergeleri için destek eklendi.
/std:clatest
veya /std:c++latest
gerektirir.
Önce:
#ifdef __cplusplus
#include <atomic>
#elif !defined(__STDC_NO_ATOMICS__)
#include <stdatomic.h>
#else
#include <custom_atomics_library.h>
#endif
Sonra:
#ifdef __cplusplus
#include <atomic>
#elifndef __STDC_NO_ATOMICS__
#include <stdatomic.h>
#else
#include <custom_atomics_library.h>
#endif
_Alignas
yapılandırılmış bir türde C'de uygulaması
C dili (C17 ve üzeri) için geçerlidir. Microsoft Visual Studio 17.9'a da eklendi
Visual Studio 2022 sürüm 17.9'dan önceki Visual C++ sürümlerinde, _Alignas
bir bildirgede yapısal bir türün hemen yanında görünürse, ISO-C Standardına göre doğru uygulanmamıştır.
// compile with /std:c17
#include <stddef.h>
struct Outer
{
_Alignas(32) struct Inner { int i; } member1;
struct Inner member2;
};
static_assert(offsetof(struct Outer, member2)==4, "incorrect alignment");
ISO-C Standardına göre, bu kod herhangi bir uyarı iletisi vermeden static_assert
derlenmelidir.
yönergesi _Alignas
yalnızca üye değişkenine member1
uygulanır.
struct Inner
hizalamasını değiştirmemelidir. Ancak Visual Studio 17.9.1'den önce, "yanlış hizalama" tanılama mesajı üretiliyordu. Derleyici, member2
'yi struct Outer
türü içinde 32 baytlık bir ofsete hizaladı.
Bu ikili uyumsuz bir değişiklik olduğundan, bu değişiklik geçerli olduğunda bir uyarı verilir. Uyarı C5274 artık önceki örnek için uyarı düzeyi 1'de gösteriliyor: warning C5274: behavior change: _Alignas no longer applies to the type 'Inner' (only applies to declared data objects)
.
Ayrıca, Visual Studio'nun önceki sürümlerinde, _Alignas
belirteci anonim bir tür tanımlayıcısı yanında göründüğünde, dikkate alınmadı.
// compile with /std:c17
#include <stddef.h>
struct S
{
_Alignas(32) struct { int anon_member; };
int k;
};
static_assert(offsetof(struct S, k)==4, "incorrect offsetof");
static_assert(sizeof(struct S)==32, "incorrect size");
Daha önce bu kod derlendiğinde her iki deyim de static_assert
hata verdi. Şimdi kod derlenir, ancak aşağıdaki düzey 1 uyarılarını yayar:
warning C5274: behavior change: _Alignas no longer applies to the type '<unnamed-tag>' (only applies to declared data objects)
warning C5273: behavior change: _Alignas on anonymous type no longer ignored (promoted members will align)
Önceki davranışı elde etmek için _Alignas(N)
ile __declspec(align(N))
'yi değiştirin.
_Alignas
'den farklı olarak, declspec(align)
türe uygulanır.
Geliştirilmiş uyarı C4706
Bu, kaynak kodunun işleyişinde aksamalara neden olan bir değişikliktir. Önceden derleyici, atama amaçlandıysa, koşullu ifadede atama için C4706 uyarısını bastırmak amacıyla atamayı parantez içine alma geleneğini algılamadı. Derleyici artık parantezleri algılar ve uyarıyı bastırır.
#pragma warning(error: 4706)
struct S
{
auto mf()
{
if (value = 9)
return value + 4;
else
return value;
}
int value = 9;
};
Derleyici artık işleve başvurulmadığı durumlarda da uyarıyı yayar. Daha önce, mf
başvurulmadığı bir satır içi işlev olduğundan, bu kod için C4706 uyarısı gösterilmiyordu. Şimdi uyarı yayılıyor:
error C4706: assignment used as a condition
note: if an assignment is intended you can enclose it in parentheses, '(e1 = e2)', to silence this warning
Bu uyarıyı düzeltmek için, amaçlanan buysa eşitlik işleci olan value == 9
'yı kullanın. Ya da atama amaçlanıyorsa, atamayı parantez içinde (value = 9)
sarın. Aksi takdirde, işlev referans verilmediğinden kaldırın.
Visual Studio 2022 sürüm 17.9'da uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.9, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Standart Şablon Kitaplığı'na yapılan değişikliklerin daha geniş bir özeti için bkz . STL Changelog VS 2022 17.9.
_Alignas
yapılandırılmış bir türde C'de uygulaması
Visual Studio 2022 sürüm 17.9'dan önceki Visual C++ sürümlerinde, _Alignas
bir bildirimde bir yapı türünün yanında göründüğünde, ISO-C Standardına göre doğru uygulanmadı. Örneğin:
// compile with /std:c17
#include <stddef.h>
struct Outer
{
_Alignas(32) struct Inner { int i; } member1;
struct Inner member2;
};
static_assert(offsetof(struct Outer, member2)==4, "incorrect alignment");
ISO-C Standardına göre, bu kod tanı mesajı vermeden static_assert
derlenebilmelidir. yönergesi _Alignas
yalnızca üye değişkenine member1
uygulanır.
struct Inner
hizalamasını değiştirmemelidir. Ancak, Visual Studio'nun 17.9.1 sürümünden önce 'yanlış hizalama' tanısı verildi. Derleyici member2
'yi struct Outer
içinde 32 bayt kaymayla hizaladı.
Bunu düzeltmek, ikili uyumluluğu bozan bir değişiklik olduğundan, davranıştaki bu değişiklik uygulandığında bir uyarı verilir. Önceki kod için, Uyarı C5274, "_Alignas
artık 'Inner' türüne uygulanmaz (yalnızca bildirilen veri nesneleri için geçerlidir)" uyarı düzeyi 1'de verilmektedir.
Visual Studio’nun önceki sürümlerinde, _Alignas
anonim tip bildiriminin yanında göründüğünde yoksayıldı. Örneğin:
// compile with /std:c17
#include <stddef.h>
struct S {
_Alignas(32) struct { int anon_member; };
int k;
};
static_assert(offsetof(struct S, k)==4, "incorrect offsetof");
static_assert(sizeof(struct S)==32, "incorrect size");
Daha önce bu kod derlendiğinde her iki deyim de static_assert
hata verdi. Kod şimdi derlenir, ancak aşağıdaki düzey 1 uyarılarıyla birlikte:
warning C5274: behavior change: _Alignas no longer applies to the type '<unnamed-tag>' (only applies to declared data objects)
warning C5273: behavior change: _Alignas on anonymous type no longer ignored (promoted members will align)
Önceki davranışı istiyorsanız, _Alignas(N)
'i __declspec(align(N))
ile değiştirin.
_Alignas
'nün aksine, declspec(align)
bir türe uygulanabilir.
__VA_OPT__
, /Zc:preprocessor
altında bir uzantı olarak etkinleştirildi.
__VA_OPT__
C++20 ve C23'e eklendi. Eklenmesinden önce, variadic makroda bir virgülü ihmal etmenin standart bir yolu yoktu. Geriye dönük daha iyi uyumluluk sağlamak için, __VA_OPT__
tüm dil sürümlerinde belirteç tabanlı ön işlemci /Zc:preprocessor
altında etkinleştirilir.
Örneğin, bu artık hatasız derlenmiş:
#define LOG_WRAPPER(message, ...) WRITE_LOG(__LINE__, message __VA_OPT__(, __VA_ARGS__))
// Failed to build under /std:c11, now succeeds.
LOG_WRAPPER("Log message");
LOG_WRAPPER("Log message with %s", "argument")
C23 dili
C23 için, /std:clatest
derleyici anahtarı kullanılırken aşağıdakiler kullanılabilir:
Tüm C dil sürümleri için aşağıdakiler kullanılabilir:
C++ Standart Kitaplığı
C++23 özellikleri
-
formattable
,range_format
,format_kind
veset_debug_format()
, P2286R8 Biçimlendirme Aralıklarının bir parçası olarak -
<mdspan>
P0009R18 gereğince ve C++23 Standardına uygulanan sonrasındaki ifade değişiklikleri. - P2510R3'e göre
işaretçiler .
Visual Studio 2022 sürüm 17.8'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.8, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
/FU
hatayla karşılaşır
C derleyicisi, bir süredir yönetilen derlemeyi desteklemese bile /FU
seçeneğini kabul ediyordu. Şimdi bir hatayla karşılaşır. Bu seçeneği geçen projelerin yalnızca C++/CLI projelerine kısıtlaması gerekir.
C++ Standart Kitaplığı
C++23'ün std
ve std.compat
adlı modülleri, /std:c++20
ile derlenirken artık kullanılabilir.
C++ Standart Kitaplığında yapılan değişikliklerin daha geniş bir özeti için bkz . STL Changelog VS 2022 17.8.
Visual Studio 2022 sürüm 17.7'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.7, Microsoft C/C++ derleyicisinde aşağıdaki vurgulanmış uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
C derleyicisine eklendi /std:clatest
Bu anahtar, C++ derleyicisi için /std:c++latest
anahtarı gibi davranır. Anahtar, hem bir sonraki taslak C standardı için önerilen mevcut tüm derleyici ve standart kitaplık özelliklerini hem de bazı tamamlanmamış ve deneysel özellikleri etkinleştirir.
C++ Standart Kitaplığı
Kütüphane <print>
artık destekleniyor. Bkz. P2093R14 Biçimlendirilmiş çıktı.
Uygulandı views::cartesian_product
.
Standart Şablon Kitaplığı'na yapılan değişikliklerin daha geniş bir özeti için bkz . STL Changelog VS 2022 17.7.
using
Uygunluk
Önceden, using
yönergesi, kullanılmaması gereken durumlarda kullanılan ad alanlarından gelen adların görünür kalmasına neden olabiliyordu. Bu, using
etkin bir yönergesi mevcut olmasa bile ad alanında bir ad bulmak için nitelenmemiş ad aramasına neden olabilir.
Yeni ve eski davranışa ilişkin bazı örnekler aşağıda verilmiştir.
Aşağıdaki açıklamalardaki "(1)" referansı, f<K>(t)
ad alanındaki A
çağrısı anlamına gelir.
namespace A
{
template<typename K, typename T>
auto f2(T t)
{
return f<K>(t); // (1) Unqualified lookup should not find anything
}
}
namespace B
{
template<typename K, typename T>
auto f(T t) noexcept
{ // Previous behavior: This function was erroneously found during unqualified lookup at (1)
return A::f2<K>(t);
}
}
namespace C
{
template<typename T>
struct S {};
template<typename, typename U>
U&& f(U&&) noexcept; // New behavior: ADL at (1) correctly finds this function
}
namespace D
{
using namespace B;
void h()
{
D::f<void>(C::S<int>());
}
}
Aynı temel sorun, daha önce derlenmiş kodun artık reddedilmesine neden olabilir:
#include <memory>
namespace Addin {}
namespace Gui
{
using namespace Addin;
}
namespace Addin
{
using namespace std;
}
// This previously compiled, but now emits error C2065 for undeclared name 'allocator'.
// This should be declared as 'std::allocator<T*>' because the using directive nominating
// 'std' is not active at this point.
template <class T, class U = allocator<T*>>
class resource_list
{
};
namespace Gui
{
typedef resource_list<int> intlist;
}
Visual Studio 2022 sürüm 17.6'da uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.6, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Bileşik volatile
atamalar artık kullanım dışı bırakılmıyor
C++20, volatile
ile nitelendirilmiş türlere belirli işleçlerin uygulanmasını kullanım dışı bıraktı. Örneğin, aşağıdaki kod ile cl /std:c++20 /Wall test.cpp
derlendiğinde:
void f(volatile int& expr)
{
++expr;
}
Derleyici üretir test.cpp(3): warning C5214: applying '++' to an operand with a volatile qualified type is deprecated in C++20
.
C++20'de bileşik atama işleçleri (formun @=
işleçleri) kullanım dışı bırakıldı. C++23'te, C++20'de dışlanan bileşik işleçler artık kullanım dışı bırakılmaz. Örneğin, C++23'te aşağıdaki kod bir uyarı üretmezken C++20'de uyarı oluşturur:
void f(volatile int& e1, int e2)
{
e1 += e2;
}
Bu değişiklik hakkında daha fazla bilgi için bkz . CWG:2654
İfadelerde eşitliğin yeniden yazılması daha az bozulmaya neden olan bir değişikliktir (P2468R2)
C++20'de P2468R2 derleyiciyi aşağıdaki gibi kodu kabul etmek üzere değiştirdi:
struct S
{
bool operator==(const S&);
bool operator!=(const S&);
};
bool b = S{} != S{};
Derleyici bu kodu kabul eder, bu da derleyicinin aşağıdaki gibi kodlarla daha katı olduğu anlamına gelir:
struct S
{
operator bool() const;
bool operator==(const S&);
};
bool b = S{} == S{};
Derleyicinin 17.5 sürümü bu programı kabul eder. Derleyicinin 17.6 sürümü bunu reddeder. Belirsizliği gidermek için const
öğesini operator==
öğesine ekleyin. Veya aşağıdaki örnekte gösterildiği gibi tanıma karşılık gelen operator!=
bir ekleyin:
struct S
{
operator bool() const;
bool operator==(const S&);
bool operator!=(const S&);
};
bool b = S{} == S{};
Microsoft C/C++ derleyici sürümleri 17.5 ve 17.6, önceki programı kabul eder ve her iki sürümde de S::operator==
çağırır.
P2468R2'da özetlenen genel programlama modeli, bir türe karşılık gelen bir operator!=
varsa, genellikle yeniden yazma davranışını bastırmasıdır. Buna karşılık gelen operator!=
ekleme, daha önce C++17'de derlenmiş kod için önerilen düzeltmedir. Daha fazla bilgi için bkz . Programlama Modeli.
Visual Studio 2022 sürüm 17.4'te uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.4, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Sabit türü olmayan kapsam dışı enum
temel türleri
Visual Studio'nun Visual Studio 2022 sürüm 17.4'den önceki sürümlerinde, C++ derleyicisi sabit temel türü olmayan temel alınmamış bir numaralandırmanın temel türünü doğru şekilde belirlemedi. altında /Zc:enumTypes
artık standart davranışı doğru şekilde uyguluyoruz.
C++ Standardı, bir enum
'ın temel aldığı türün, o enum
içindeki tüm numaralandırıcıları barındırabilecek kadar büyük olmasını gerektirir. Yeterince büyük numaralandırıcılar, alttaki türü enum
'ün unsigned int
, long long
veya unsigned long long
olarak ayarlayabilir. Daha önce, numaralandırıcı değerlerinden bağımsız olarak, böyle enum
türleri Microsoft derleyicisinde her zaman int
türüne sahipti.
Etkinleştirildiğinde, /Zc:enumTypes
seçeneği potansiyel bir kaynak ve ikili uyumluluk bozulmasına neden olabilecek bir değişikliktir. Düzeltme ikili uyumluluğu etkileyebileceğinden varsayılan olarak kapalıdır ve tarafından /permissive-
etkinleştirilmez. Uyumlu düzeltme etkinleştirildiğinde bazı numaralandırma türleri boyut değiştirir. Bazı Windows SDK üst bilgileri bu tür numaralandırma tanımlarını içerir.
Örnek
enum Unsigned
{
A = 0xFFFFFFFF // Value 'A' does not fit in 'int'.
};
// Previously, failed this static_assert. Now passes with /Zc:enumTypes.
static_assert(std::is_same_v<std::underlying_type_t<Unsigned>, unsigned int>);
template <typename T>
void f(T x)
{
}
int main()
{
// Previously called f<int>, now calls f<unsigned int>.
f(+A);
}
// Previously this enum would have an underlying type of `int`, but Standard C++ requires this to have
// a 64-bit underlying type. Using /Zc:enumTypes changes the size of this enum from 4 to 8, which could
// impact binary compatibility with code compiled with an earlier compiler version or without the switch.
enum Changed
{
X = -1,
Y = 0xFFFFFFFF
};
Sabit bir temel türü olmayan bir enum
tanım içindeki numaralandırıcı türleri
Visual Studio'nun Visual Studio 2022 sürüm 17.4'den önceki sürümlerinde, C++ derleyicisi numaralandırıcı türlerini doğru modellemedi. Numaralandırmanın kapanış ayracına gelmeden önce, sabit bir temel türü olmayan numaralandırmalarda yanlış bir tür varsayılabilir. altında /Zc:enumTypes
, derleyici artık standart davranışı doğru şekilde uygular.
C++ Standardı, sabit temel alınmamış bir numaralandırma tanımında başlatıcıların numaralandırıcı türlerini belirlediğini belirtir. Veya başlatıcısı olmayan numaralandırıcılar için, önceki numaralandırıcının türüne göre (taşmayı göz önünde bulundurarak). Daha önce, bu tür numaralandırıcılara her zaman temel alınan tür için bir yer tutucuyla (genellikle int
) numaralandırmanın çıkarılmış türü verilirdi.
Etkinleştirildiğinde, /Zc:enumTypes
seçeneği potansiyel bir kaynak ve ikili uyumluluk bozulmasına neden olabilecek bir değişikliktir. Düzeltme ikili uyumluluğu etkileyebileceğinden varsayılan olarak kapalıdır ve tarafından /permissive-
etkinleştirilmez. Uyumlu düzeltme etkinleştirildiğinde bazı numaralandırma türleri boyut değiştirir. Bazı Windows SDK üst bilgileri bu tür numaralandırma tanımlarını içerir.
Örnek
enum Enum {
A = 'A',
B = sizeof(A)
};
static_assert(B == 1); // previously failed, now succeeds under /Zc:enumTypes
Bu örnekte, numaralandırıcının A
, numaralandırmanın kapanış ayracından önce char
türünde olmalıdır, bu nedenle B
, sizeof(char)
kullanılarak başlatılmalıdır. Düzeltmeden /Zc:enumTypes
önce, A
hem çıkarılan bir temel tür ile bir numaralandırma türüne (Enum
, int
) sahipti ve B
veya 4 kullanılarak sizeof(Enum)
başlatıldı.
Visual Studio 2022 sürüm 17.3'te uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.3, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
C: İşaretçiler arasında geliştirilmiş değiştirici uyumluluk denetimi
C derleyicisi, özellikle void*
işaretçiler arasındaki değiştiricileri düzgün karşılaştırmadı. Bu hata, const int**
ve void*
arasında uyumsuzluk, int* volatile*
ve void*
arasında ise uyumluluğun hatalı teşhisine yol açabilir.
Örnek
void fn(void* pv) { (pv); }
int main()
{
int t = 42;
int* pt = &t;
int* volatile * i = &pt;
fn(i); // Now raises C4090
const int** j = &pt;
fn(j); // No longer raises C4090
}
Visual Studio 2022 sürüm 17.2'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.2, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Tamamlanmamış çift yönlü karakter uyarıları
Visual Studio 2022 sürüm 17.2, açıklamalar ve dizelerdeki sonlandırılmamış Unicode çift yönlü karakterler için düzey 3 uyarısı C5255 ekler. Uyarı, Truva Atı Kaynağı: Nicholas Boucher ve Ross Anderson tarafından oluşturulan Görünmez Güvenlik Açıkları başlığı altında açıklanan güvenlik endişesini giderir. Unicode çift yönlü karakterler hakkında daha fazla bilgi için bkz . Unicode® Standart Ek #9: UNICODE ÇIFT YÖNLÜ ALGORITMA.
Uyarı C5255 yalnızca dönüştürmeden sonra Unicode çift yönlü karakterler içeren dosyaları ele alır. Bu uyarı UTF-8, UTF-16 ve UTF-32 dosyaları için geçerlidir, bu nedenle doğru kaynak kodlama sağlanmalıdır. Bu değişiklik kaynak uyumsuzluğuna neden olan bir değişikliktir.
Örnek (önce/sonra)
Visual Studio 2022 sürüm 17.2'den önceki Visual Studio sürümlerinde, tamamlanmamış bir çift yönlü karakter uyarı üretmiyordu. Visual Studio 2022 sürüm 17.2 uyarı C5255 üretir:
// bidi.cpp
int main() {
const char *access_level = "user";
// The following source line contains bidirectional Unicode characters equivalent to:
// if ( strcmp(access_level, "user\u202e \u2066// Check if admin \u2069 \u2066") ) {
// In most editors, it's rendered as:
// if ( strcmp(access_level, "user") ) { // Check if admin
if ( strcmp(access_level, "user // Check if admin ") ) {
printf("You are an admin.\n");
}
return 0;
}
/* build output
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+202e'
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+2066'
*/
from_chars()
float
beraberlik bozucu
Visual Studio 2022 sürüm 17.2, tiebreaker kurallarında <charconv>
from_chars()
float
yanlış sonuçlar üreten bir hatayı düzeltir. Bu hata, dar bir aralık içinde ardışık float
değerlerin tam orta noktasında olan ondalık dizeleri etkiledi. (En küçük ve en büyük etkilenen değerler sırasıyla 32768.009765625
ve 131071.98828125
'ydi.) Tiebreaker kuralı "çift"e yuvarlamak istedi ve "çift" "aşağı" anlamına geliyordu, ancak uygulama yanlışlıkla "yukarı" yuvarladı (double
etkilenmedi). Daha fazla bilgi ve uygulama ayrıntıları için bkz. microsoft/STL#2366.
Bu değişiklik, belirtilen durum aralığındaki çalışma zamanı davranışını etkiler:
Örnek
// from_chars_float.cpp
#include <cassert>
#include <charconv>
#include <cstdio>
#include <string_view>
#include <system_error>
using namespace std;
int main() {
const double dbl = 32768.009765625;
const auto sv = "32768.009765625"sv;
float flt = 0.0f;
const auto result = from_chars(sv.data(), sv.data() + sv.size(), flt);
assert(result.ec == errc{});
printf("from_chars() returned: %.1000g\n", flt);
printf("This rounded %s.\n", flt < dbl ? "DOWN" : "UP");
}
Visual Studio 2022 sürüm 17.2'nin önceki sürümlerinde:
C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.01171875
This rounded UP.
Visual Studio 2022 sürüm 17.2 ve sonrasında:
C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.0078125
This rounded DOWN.
/Zc:__STDC__
, __STDC__
’yi C için kullanılabilir hale getirir.
C standardı, uyumlu bir C uygulamasının __STDC__
'ı 1
olarak tanımlamasını gerektirir. UCRT'nin, __STDC__
1
olduğunda POSIX işlevlerini kullanıma sunmayan davranışı nedeniyle, bu makroyu C için varsayılan olarak tanımlamak, kararlı dil sürümlerinde hataya neden olan değişiklikler yapmadan mümkün değildir. Visual Studio 2022 sürüm 17.2 ve üzeri, bu makroları tanımlayan bir uyumluluk seçeneği /Zc:__STDC__
ekler. Seçeneğin olumsuz bir sürümü yoktur. Şu anda bu seçeneği C'nin gelecekteki sürümleri için varsayılan olarak kullanmayı planlıyoruz.
Bu değişiklik kaynak uyumsuzluğuna neden olan bir değişikliktir. C11 veya C17 modu etkinleştirildiğinde (/std:c11
veya /std:c17
) ve /Zc:__STDC__
belirtildiğinde geçerlidir.
Örnek
// test__STDC__.c
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
int main() {
#if __STDC__
int f = _open("file.txt", _O_RDONLY);
_close(f);
#else
int f = open("file.txt", O_RDONLY);
close(f);
#endif
}
/* Command line behavior
C:\Temp>cl /EHsc /W4 /Zc:__STDC__ test__STDC__.c && test__STDC__
*/
Eksik küme ayraçları için uyarı
Uyarı C5246, toplu başlatma sırasında bir alt nesnenin küme ayraçlarının eksik olduğunu bildirir. Visual Studio 2022 sürüm 17.2'den önce, uyarı anonim struct
veya union
durumunu işlemedi.
Bu değişiklik kaynak uyumsuzluğuna neden olan bir değişikliktir. Varsayılan olarak kapalı C5246 uyarısı etkinleştirildiğinde geçerlidir.
Örnek
Visual Studio 2022 sürüm 17.2 ve sonraki sürümlerinde bu kod artık bir hataya neden oluyor:
struct S {
union {
float f[4];
double d[2];
};
};
void f()
{
S s = { 1.0f, 2.0f, 3.14f, 4.0f };
}
/* Command line behavior
cl /Wall /c t.cpp
t.cpp(10): warning C5246: 'anonymous struct or union': the initialization of a subobject should be wrapped in braces
*/
Bu sorunu çözmek için başlatıcıya küme ayraçları ekleyin.
void f()
{
S s = { { 1.0f, 2.0f, 3.14f, 4.0f } };
}
Visual Studio 2022 sürüm 17.1'de uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.1, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Yerel olmayan lambda ifadeleri içinde hatalı biçimlendirilmiş yakalama varsayılanını algılama
C++ Standardı yalnızca blok kapsamındaki bir lambda ifadesinin yakalama varsayılanı olmasına izin verir. Visual Studio 2022 sürüm 17.1 ve sonraki sürümlerde derleyici, yerel olmayan bir lambda ifadesinde bir yakalama varsayılanına izin verilmediğini tespit eder. C5253 adlı yeni bir düzey 4 uyarısı yayar.
Bu değişiklik kaynak uyumsuzluğuna neden olan bir değişikliktir. Yeni lambda işlemcisini kullanan herhangi bir modda geçerlidir: /Zc:lambda
, /std:c++20
veya /std:c++latest
.
Örnek
Visual Studio 2022 sürüm 17.1'de bu kod artık bir hata yayar:
#pragma warning(error:5253)
auto incr = [=](int value) { return value + 1; };
// capture_default.cpp(3,14): error C5253: a nonlocal lambda cannot have a capture default
// auto incr = [=](int value) { return value + 1; };
// ^
Bu sorunu düzeltmek için yakalama varsayılanını kaldırın:
#pragma warning(error:5253)
auto incr = [](int value) { return value + 1; };
C4028 artık işlevden işaretçiye işlemler için C4133'dür
Visual Studio 2022 sürüm 17.1'den önce, derleyici C kodundaki belirli işlev işaretçisi karşılaştırmalarında yanlış bir hata iletisi bildirdi. Aynı bağımsız değişken sayılarına ama uyumsuz türlere sahip iki işlev işaretçisini karşılaştırdığınızda yanlış ileti bildirildi. Şimdi işlev parametresi uyuşmazlığı yerine işaretçiden işleve uyumsuzluktan şikayet eden farklı bir uyarı yayınlıyoruz.
Bu değişiklik kaynak uyumsuzluğuna neden olan bir değişikliktir. Kod C olarak derlendiğinde uygulanır.
Örnek
int f1(int);
int f2(char*);
int main(void)
{
return (f1 == f2);
}
// Old warning:
// C4028: formal parameter 1 different from declaration
// New warning:
// C4113: 'int (__cdecl *)(char *)' differs in parameter lists from 'int (__cdecl *)(int)'
Bağımsız olmayan bir unsurda hata static_assert
Visual Studio 2022'nin 17.1 ve sonraki sürümlerinde, static_assert
ile ilişkili ifade bağımlı bir ifade değilse, derleyici ifadeyi ayrıştırıldığında değerlendirir. İfade false
olarak değerlendirildiğinde, derleyici bir hata verir. Daha önce, static_assert
bir işlev şablonunun gövdesindeyse (veya bir sınıf şablonunun üye işlevinin gövdesindeyse), derleyici bu analizi gerçekleştirmezdi.
Bu değişiklik kaynak uyumsuzluğuna neden olan bir değişikliktir.
/permissive-
veya /Zc:static_assert
ima eden herhangi bir modda geçerlidir. Bu davranış değişikliği, derleyici seçeneği kullanılarak /Zc:static_assert-
devre dışı bırakılabilir.
Örnek
Visual Studio 2022 sürüm 17.1 ve sonraki sürümlerinde bu kod artık bir hataya neden oluyor:
template<typename T>
void f()
{
static_assert(false, "BOOM!");
}
Bu sorunu düzeltmek için ifadeyi bağımlı hale getirin. Örneğin:
template<typename>
constexpr bool dependent_false = false;
template<typename T>
void f()
{
static_assert(dependent_false<T>, "BOOM!");
}
Bu değişiklikle, derleyici yalnızca işlev şablonu f
örneği oluşturulursa hata gösterir.
Visual Studio 2022 sürüm 17.0'da uyumluluk geliştirmeleri
Visual Studio 2022 sürüm 17.0, Microsoft C/C++ derleyicisinde aşağıdaki uyumluluk iyileştirmelerini, hata düzeltmelerini ve davranış değişikliklerini içerir.
Numaralandırma türü için bit alanı genişliği uyarısı
Bir sabit listesi türünün örneğini bit alanı olarak bildirdiğinizde, bit alanının genişliği numaralandırmanın tüm olası değerlerini barındırmalıdır. Aksi takdirde, derleyici bir tanılama iletisi verir. Şu örneği göz önünde bulundurun: Göz önünde bulundurun:
enum class E : unsigned { Zero, One, Two };
struct S {
E e : 1;
};
Programcı, sınıf üyesinin S::e
açıkça adlandırılmış enum
değerlerden herhangi birini barındırabilmesini bekleyebilir. Numaralandırma öğelerinin sayısı göz önünde bulundurulduğunda, bu mümkün değildir. bit alanı, E
'ün açıkça sağlanan değerlerinin aralığını (kavramsal olarak 'nin E
) kaplayamaz. Bit alanı genişliğinin numaralandırmanın etki alanı için yeterince büyük olmadığı endişesini gidermek için MSVC'ye yeni bir (varsayılan olarak kapalı) uyarısı eklenir:
t.cpp(4,5): warning C5249: 'S::e' of type 'E' has named enumerators with values that cannot be represented in the given bit field width of '1'.
E e : 1;
^
t.cpp(1,38): note: see enumerator 'E::Two' with value '2'
enum class E : unsigned { Zero, One, Two };
^
Bu derleyici davranışı, tüm /std
ve /permissive
modlarını etkileyen bir kaynak ve ikili uyumluluk kırıcı değişikliktir.
Sıralı işaretçi nullptr
veya 0 ile karşılaştırmasında hata
C++ Standardı, bilmeden nullptr
veya 0 ile sıralı bir işaretçi karşılaştırmasına izin verdi. Örneğin:
bool f(int *p)
{
return p >= 0;
}
WG21 tarafından belge N3478 bu ihmali kaldırdı. Bu değişiklik MSVC'de uygulanır. Örnek /permissive-
(ve /diagnostics:caret
) kullanılarak derlendiğinde aşağıdaki hata oluşur:
t.cpp(3,14): error C7664: '>=': ordered comparison of pointer and integer zero ('int *' and 'int')
return p >= 0;
^
Bu derleyici davranışı, tüm /permissive-
modlarında /std
kullanılarak derlenen kodu etkileyen bir kaynak ve ikili uyumsuzluk değişikliğidir.