(Arka plan: C ve C ++ derleyicilerini uygulamada bazı deneyimim var.)
C99'daki değişken uzunluklu diziler temelde bir yanlış adımdı. VLA'ları desteklemek için, C99 sağduyu için aşağıdaki tavizleri vermek zorunda kaldı:
sizeof x
artık her zaman bir derleme zamanı sabiti değildir; derleyici bazen sizeof
çalışma zamanında bir-ifade değerlendirmek için kod oluşturmak gerekir .
İki boyutlu VLAS izin ( int A[x][y]
) parametre olarak 2D VLAS almak işlevlerini bildirmek için yeni bir sözdizimi gerekli: void foo(int n, int A[][*])
.
C ++ dünyasında daha az önemli olan, ancak C'nin gömülü sistem programcılarının hedef kitlesi için son derece önemlidir, bir VLA bildirmek, yığınızın keyfi olarak büyük bir yığınını parçalamak anlamına gelir . Bu, garantili bir yığın taşması ve çökmesidir. (Eğer beyan Herzaman int A[n]
, sen dolaylı 2GB yedek için yığının olduğunu iddia ediyoruz. Sonuçta, bilirseniz n
"o zaman sadece ilan edeceğini kesinlikle daha az burada 1000'den olduğunu" int A[1000]
. 32 bit tamsayı ikame n
için 1000
bir itirafıdır programınızın davranışının ne olması gerektiği hakkında hiçbir fikriniz yok.)
Tamam, şimdi C ++ hakkında konuşmaya geçelim. C ++ 'da, C89'un yaptığı "tip sistemi" ve "değer sistemi" arasında aynı güçlü ayırım var… ama gerçekten C'nin sahip olmadığı şekillerde buna güvenmeye başladık. Örneğin:
template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s; // equivalently, S<int[n]> s;
Eğer n
bir derleme zamanı sabiti olmasaydı (yani, A
değişken olarak değiştirilmiş tipte olsaydı), o zaman ne tür bir yer olurdu S
? Misiniz S
'ın tipi de sadece çalışma zamanında belirlenecek?
Peki buna ne dersin:
template<typename T> bool myfunc(T& t1, T& t2) { ... };
int A1[n1], A2[n2];
myfunc(A1, A2);
Derleyici, bazı örneklemeler için kod oluşturmalıdır myfunc
. Bu kod neye benzemeli? Türünü bilmiyorsak, bu kodu statik olarak nasıl oluşturabilirizA1
Derleme zamanında ?
Daha da kötüsü, ne zamanında ortaya çıkarsa o n1 != n2
, böylece !std::is_same<decltype(A1), decltype(A2)>()
? Bu durumda, çağrı myfunc
derleme bile olmamalıdır şablon türü kesinti başarısız olduğundan olmamalıdır! Çalışma zamanında bu davranışı nasıl taklit edebiliriz?
Temel olarak, C ++ gittikçe daha fazla kararı derleme zamanına itme yönünde ilerliyor : şablon kodu oluşturma, constexpr
işlev değerlendirme, vb. Bu arada, C99 geleneksel olarak derleme zamanı kararlarını (örneğin sizeof
) çalışma zamanına sokmakla meşguldü . Bunu akılda tutarak, C99 tarzı VLA'ları C ++ ile entegre etmeye çalışırken herhangi bir çaba harcamak gerçekten mantıklı mı?
Diğer her yanıtlayıcının işaret ettiği gibi, C ++, "Ne kadar RAM'e ihtiyacım olabileceğine dair hiçbir fikrim yok" fikrini iletmek istediğinizde birçok yığın ayırma mekanizması ( std::unique_ptr<int[]> A = new int[n];
veya std::vector<int> A(n);
bariz olanlar) sağlar. Ve C ++, ihtiyacınız olan RAM miktarının sahip olduğunuz RAM miktarından daha büyük olduğu kaçınılmaz durumla başa çıkmak için şık bir istisna işleme modeli sağlar. Ama umarım bu cevap, C99 tarzı VLA'ların neden C ++ için iyi bir uyum olmadığını ve C99 için gerçekten iyi bir uyum olmadığını iyi bir fikir verir . ;)
Konu hakkında daha fazla bilgi için , Bjarne Stroustrup'un Ekim 2013 tarihli VLA'lar makalesi olan N3810 "Dizi Uzantılarına Alternatifler" konusuna bakın . Bjarne'nin POV'si benimkinden çok farklı; N3810 daha iyi şeyler için iyi bir C ++ ish sözdizimi bulmaya ve C ++ ' da ham dizilerin kullanılmasını engellemeye odaklanırken, daha çok metaprogramlama ve yazım sistemi üzerindeki etkilere odaklandım. Metaprogramlama / dizgi sistemi sonuçlarını çözülmüş, çözülebilir ya da sadece ilgisiz görüp görmediğini bilmiyorum.
Aynı noktaların çoğuna isabet eden iyi bir blog yazısı "Değişken Uzunluk Dizilerinin Meşru Kullanımı" dır (Chris Wellons, 2019-10-27).