Evet, aynı kodun C ++ 03 ve C ++ 11 arasında farklı davranışlarla sonuçlanmasına neden olacak değişiklik sayısı vardır. Sıralama kuralları farklılıkları, önceden tanımlanmamış bazı davranışların iyi tanımlanması da dahil olmak üzere bazı ilginç değişiklikler yapar.
1. bir başlatıcı listesinde aynı değişkenin birden fazla mutasyon
Çok ilginç bir köşe örneği, bir başlatıcı listesinde aynı değişkenin birden fazla mutasyonunu yapar, örneğin:
int main()
{
int count = 0 ;
int arrInt[2] = { count++, count++ } ;
return 0 ;
}
Hem C ++ 03 hem de C ++ 11'de bu iyi tanımlanmıştır, ancak C ++ 03'teki değerlendirme sırası belirsizdir, ancak C ++ 11'de göründükleri sırayla değerlendirilirler . Bu yüzden clang
C ++ 03 modunda kullanarak derlersek aşağıdaki uyarıyı sağlar ( canlı olarak görün ):
warning: multiple unsequenced modifications to 'count' [-Wunsequenced]
int arrInt[2] = { count++, count++ } ;
^ ~~
ancak C ++ 11'de bir uyarı sağlamaz ( canlı yayına bakın ).
2. Yeni sıralama kuralları i = ++ i + 1 yapar; C ++ 11'de iyi tanımlanmış
C ++ 03'ten sonra kabul edilen yeni sıralama kuralları şu anlama gelir:
int i = 0 ;
i = ++ i + 1;
artık C ++ 11'de tanımlanmamış bir davranış değildir, bu durum 637 hata raporunda ele alınmıştır. Sıralama kuralları ve örnek katılmıyorum
3. Yeni sıralama kuralları da ++++ i yapar; C ++ 11'de iyi tanımlanmış
C ++ 03'ten sonra kabul edilen yeni sıralama kuralları şu anlama gelir:
int i = 0 ;
++++i ;
artık C ++ 11'de tanımlanmamış bir davranış değildir.
4. Biraz Daha Duyarlı İmzalı Sol Vites
Daha sonra C ++ 11 taslakları, N3485
aşağıda bağladığım , 1 biti işaret bitine veya işaret bitine geçirmenin tanımlanmamış davranışını düzeltti . Bu durum ayrıca 1457 hata raporunda da yer almaktadır . Howard Hinnant , C ++ 11'de sol kayma (<<) negatif tamsayı tanımsız bir davranış mıdır? Konusundaki bu değişikliğin önemini yorumladı. .
5. constexpr fonksiyonları C ++ 11 derleme zaman sabiti ifadeleri olarak ele alınabilir
C ++ 11, aşağıdakileri içeren constexpr işlevlerini tanıttı :
Constexpr belirteci, derleme zamanında işlevin veya değişkenin değerini değerlendirmenin mümkün olduğunu bildirir. Bu tür değişkenler ve fonksiyonlar daha sonra sadece derleme zaman sabiti ifadelerine izin verildiğinde kullanılabilir.
C ++ 03 constexpr özelliğine sahip olmasa da , standart kitaplık C ++ 11'de constexpr olarak birçok işlev sağladığı için açıkça constexpr anahtar sözcüğünü kullanmak zorunda değiliz . Örneğin std :: numeric_limits :: min . Farklı davranışlara yol açabilir, örneğin:
#include <limits>
int main()
{
int x[std::numeric_limits<unsigned int>::min()+2] ;
}
Kullanma clang
neden olur 03, bu C ++ x
olan bir değişken uzunluklu dizi olmak bir uzantısı ve aşağıdaki uyarıyı oluşturur:
warning: variable length arrays are a C99 feature [-Wvla-extension]
int x[std::numeric_limits<unsigned int>::min()+2] ;
^
C ++ 11 std::numeric_limits<unsigned int>::min()+2
ise derleme zamanı sabit bir ifadedir ve VLA uzantısını gerektirmez.
6. C ++ 11'de, yıkıcılarınız için dolaylı istisna özellikleri dolaylı olarak oluşturulur
C ++ 11'de kullanıcı tanımlı yıkıcı, istisnasız yıkıcılardanoexcept(true)
açıklandığı gibi örtülü spesifikasyona sahip olduğundan, aşağıdaki programın anlamı:
#include <iostream>
#include <stdexcept>
struct S
{
~S() { throw std::runtime_error(""); } // bad, but acceptable
};
int main()
{
try { S s; }
catch (...) {
std::cerr << "exception occurred";
}
std::cout << "success";
}
C ++ 11'de arayacak std::terminate
ancak C ++ 03'te başarıyla çalışacaktır.
7. C ++ 03'te, şablon bağımsız değişkenlerinin dahili bağlantısı olamazdı
Bu güzel kaplıdır Why std :: karşılaştırın sınıfları kabul etmeyen sıralama Bir işlev içinde bildirilen . Bu nedenle, aşağıdaki kod C ++ 03'de çalışmamalıdır:
#include <iostream>
#include <vector>
#include <algorithm>
class Comparators
{
public:
bool operator()(int first, int second)
{
return first < second;
}
};
int main()
{
class ComparatorsInner : public Comparators{};
std::vector<int> compares ;
compares.push_back(20) ;
compares.push_back(10) ;
compares.push_back(30) ;
ComparatorsInner comparatorInner;
std::sort(compares.begin(), compares.end(), comparatorInner);
std::vector<int>::iterator it;
for(it = compares.begin(); it != compares.end(); ++it)
{
std::cout << (*it) << std::endl;
}
}
ancak şu anda clang
bu kod C ++ 03 modunda izin veriyorsa -pedantic-errors
, biraz icky olan bayrağı kullanmazsanız , canlı olarak görün .
8. >> birden fazla şablon kapatılırken artık kötü biçimlendirilmemiş
>>
Birden çok şablonu kapatmak için kullanmak artık yanlış biçimlendirilmiş değildir ancak C ++ 03 ve C + 11'de farklı sonuçlara sahip kodlara yol açabilir. Aşağıdaki örnek Sağ açılı ayraçlardan ve geriye dönük uyumluluktan alınmıştır :
#include <iostream>
template<int I> struct X {
static int const c = 2;
};
template<> struct X<0> {
typedef int c;
};
template<typename T> struct Y {
static int const c = 3;
};
static int const c = 4;
int main() {
std::cout << (Y<X<1> >::c >::c>::c) << '\n';
std::cout << (Y<X< 1>>::c >::c>::c) << '\n';
}
ve C ++ 03'teki sonuç:
0
3
ve C ++ 11'de:
0
0
9. C ++ 11 std :: vector yapıcılarının bazılarını değiştirir
Bu yanıttan biraz değiştirilmiş kod , std :: vector'dan aşağıdaki kurucuyu kullanmanın :
std::vector<T> test(1);
C ++ 03 ve C ++ 11'de farklı sonuçlar üretir:
#include <iostream>
#include <vector>
struct T
{
bool flag;
T() : flag(false) {}
T(const T&) : flag(true) {}
};
int main()
{
std::vector<T> test(1);
bool is_cpp11 = !test[0].flag;
std::cout << is_cpp11 << std::endl ;
}
10. Toplu başlatıcılarda dönüşümleri daraltma
C ++ 11'de, toplam başlatıcılardaki daralma dönüşümü kötü biçimlendirilmiştir ve gcc
C ++ 11'de varsayılan olarak bir uyarı sağlamasına rağmen hem C ++ 11 hem de C ++ 03'te buna izin verir gibi görünüyor :
int x[] = { 2.0 };
Bu taslak C ++ 11 standart bölümünde 8.5.4
Liste başlatma paragrafı 3'te ele alınmıştır :
Bir nesnenin listeye başlatılması veya T tip referansı aşağıdaki gibi tanımlanır:
ve aşağıdaki madde işaretini içerir ( vurgu mayın ):
Aksi takdirde, T bir sınıf tipiyse yapıcılar dikkate alınır. Uygulanabilir yapıcılar numaralandırılır ve en iyisi aşırı yük çözünürlüğü (13.3, 13.3.1.7) ile seçilir. Bağımsız değişkenlerden herhangi birini dönüştürmek için daraltma dönüşümü (aşağıya bakın) gerekiyorsa, program kötü biçimlendirilmiştir
Bu ve daha birçok örnek taslak C ++ standart bölümü annex C.2
C ++ ve ISO C ++ 2003'te ele alınmıştır . Ayrıca şunları içerir:
Yeni dize değişmezleri [...] Özellikle, R, u8, u8R, u, uR, U, UR veya LR adlı makrolar bir dize değişmezine bitişikken genişletilmez, ancak dize değişmezinin bir parçası olarak yorumlanır . Örneğin
#define u8 "abc"
const char *s = u8"def"; // Previously "abcdef", now "def"
Kullanıcı tanımlı değişmez dize desteği [...] Daha önce, # 1 iki ayrı önişleme belirtecinden oluşacaktı ve _x makrosu genişletilecekti. Bu Uluslararası Standartta, # 1 tek bir önişleme belirteçinden oluşur, bu nedenle makro genişletilmez.
#define _x "there"
"hello"_x // #1
Tamsayı bölme kullanan tamsayı / ve% [...] 2003 kod sonuçları için yuvarlamayı belirtin, sonucu 0'a veya negatif sonsuza doğru yuvarlar, oysa bu Uluslararası Standart her zaman sonucu 0'a yuvarlar.
Size () üye işlevlerinin karmaşıklığı artık sabittir [...] C ++ 2003 ile uyumlu bazı kap uygulamaları bu Uluslararası Standartta belirtilen boyut () gereksinimlerine uymayabilir. Std :: list gibi kapların daha katı gereksinimlere göre ayarlanması uyumsuz değişiklikler gerektirebilir.
Std :: ios_base :: başarısızlık temel sınıfını değiştirin [...] std :: ios_base :: başarısızlık artık doğrudan std :: istisnadan türetilmiyor, ancak artık std :: system_error kaynağından türetiliyor. std :: runtime_error. Std :: ios_base :: hatasının doğrudan std :: istisnadan türetildiğini varsayan geçerli C ++ 2003 kodu, bu Uluslararası Standartta farklı şekilde çalışabilir.
auto
bir durumla sonuçlanabilir