Neden değişken uzunluklu diziler C ++ standardının bir parçası değildir?


326

Son birkaç yıldır C'yi çok kullanmadım. Bu soruyu okuduğumdaBugün , bilmediğim bazı C sözdizimiyle karşılaştım.

Görünüşe göre C99'da aşağıdaki sözdizimi geçerlidir:

void foo(int n) {
    int values[n]; //Declare a variable length array
}

Bu oldukça kullanışlı bir özellik gibi görünüyor. C ++ standardına eklemeyle ilgili bir tartışma oldu mu ve eğer öyleyse, neden atlandı?

Bazı olası nedenler:

  • Derleyici satıcılarının uygulayacağı tüylü
  • Standardın başka bir kısmı ile uyumsuz
  • İşlevsellik diğer C ++ yapılarıyla taklit edilebilir

C ++ standardı, dizi boyutunun sabit bir ifade olması gerektiğini belirtir (8.3.4.1).

Evet, elbette, oyuncak örneğinde birinin kullanabileceğini anlıyorum std::vector<int> values(m);, ancak bu, yığından değil yığından bellek ayırıyor. Ve eğer ben çok boyutlu bir dizi istiyorsanız:

void foo(int x, int y, int z) {
    int values[x][y][z]; // Declare a variable length array
}

vectorversiyon oldukça hantal hale gelir:

void foo(int x, int y, int z) {
    vector< vector< vector<int> > > values( /* Really painful expression here. */);
}

Dilimler, satırlar ve sütunlar da tüm belleğe yayılacaktır.

Tartışmaya bakıldığında, comp.std.c++bu sorunun argümanın her iki tarafında çok ağır isimlerle oldukça tartışmalı olduğu açıktır. A'nın std::vectorher zaman daha iyi bir çözüm olduğu kesinlikle açık değildir .


3
Sadece meraktan, neden yığına tahsis edilmesi gerekiyor? Öbek dağılımı performans sorunlarından korkuyor musunuz?
Dimitri

32
@Dimitri Gerçekten değil, ancak yığın tahsisinin yığın tahsisinden daha hızlı olacağı inkar edilemez. Ve bazı durumlarda bu önemli olabilir.
Andreas Brinck

11
Değişken uzunluktaki ana avantaj, tüm verilerin birbirine yakın olması nedeniyle diziler arasında yinelendiğinde yan yana bayt okur ve yazarsınız. Verileriniz önbelleğe alınır ve cpu baytları belleğe / belleğe göndermeden ve göndermeden üzerinde çalışabilir.
Calmarius

4
Önişlemci sabitlerini statik sabit değişkenlerle değiştirmek için değişken uzunluklu diziler de kullanılabilir. Ayrıca C'de VLA için başka bir seçeneğiniz yoktur ve bazen taşınabilir C / C ++ kodu yazmak gerekir (her iki derleyiciyle de uyumludur).
Yury

2
bir yana, clang ++ VLA'lara izin veriyor gibi görünüyor.
user3426763

Yanıtlar:


204

Son zamanlarda bunun usenet'te başladığı bir tartışma vardı: C ++ 0x'de neden VLA yok .

Yığında, genellikle sadece çok az alanı olan potansiyel büyük bir dizi oluşturmak zorunda kalmanın iyi olmadığını kabul eden insanlarla aynı fikirdeyim. Argüman, önceden boyutu biliyorsanız, statik bir dizi kullanabilirsiniz. Ve önceden boyutu bilmiyorsanız, güvenli olmayan bir kod yazacaksınız.

C99 VLA'lar, alanı boşa harcamadan veya kullanılmayan elemanlar için kurucuları çağırmadan küçük diziler oluşturabilmenin küçük bir yararı olabilir, ancak tür sistemine oldukça büyük değişiklikler getirirler (çalışma zamanı değerlerine bağlı olarak türleri belirtebilirsiniz - bu geçerli C ++ 'da henüz mevcut değil, new operatör türü belirteçleri , özel olarak ele alınırlar, böylece çalışma zamanı newoperatörün kapsamından kaçmaz).

Kullanabilirsiniz std::vector, ancak dinamik bellek kullandığı için tamamen aynı değildir ve kişinin kendi yığın ayırıcısını kullanması tam olarak kolay değildir (hizalama da bir sorundur). Aynı sorunu çözmez, çünkü bir vektör yeniden boyutlandırılabilir bir kapsayıcıdır, oysa VLA'lar sabit boyutludur. C ++ Dinamik Dizi önerisi VLA tabanlı bir dile alternatif olarak, bir kütüphane tabanlı bir çözüm tanıtmak için tasarlanmıştır. Ancak, bildiğim kadarıyla C ++ 0x'in bir parçası olmayacak.


22
+1 ve kabul edildi. Bir yorum olsa da, güvenlik argümanı biraz zayıf olduğunu düşünüyorum çünkü yığın taşmalarına neden olmanın birçok yolu var. Güvenlik argümanı, asla özyineleme kullanmamanız ve tüm nesneleri yığıntan ayırmanız gereken konumu desteklemek için kullanılabilir .
Andreas Brinck

17
Diyorsunuz ki, yığın taşmalarına neden olmanın başka yolları olduğundan, bunlardan daha fazlasını teşvik edebiliriz?
jalf

3
@ Andreas, zayıflık konusunda anlaştılar. Ancak özyineleme için, yığın yenene kadar çok sayıda çağrı alır ve bu durumda insanlar yinelemeyi kullanırdı. Usenet ipliğindeki bazı insanların söylediği gibi, bu her durumda VLA'lara karşı bir argüman değildir, çünkü bazen kesinlikle bir üst sınır biliyor olabilirsiniz. Ama bu durumlarda, yine de fazla yer israf olmaz çünkü ben, statik bir dizi eşit yeterli olabilir gördüğünüzden (o eğer olur , o zaman aslında yığın alanı yeterince büyük tekrar olup olmadığını sormak gerekir).
Johannes Schaub - litb

10
Ayrıca Matt Austern'in bu konudaki cevabına bakın: C ++ için daha katı tip eşleşmeleri nedeniyle VLA'ların dil spesifikasyonu muhtemelen C + için oldukça daha karmaşık olacaktır (örnek: C, C ++ ' T(*)[]a a T(*)[N]- atamasına izin verir, çünkü C ++ "tür uyumluluğu" hakkında bilgi sahibi değildir - tam eşleşme gerektirir), tür parametreleri, istisnalar, con- ve yıkıcılar ve eşyalar. VLA'ların faydalarının tüm bu işleri gerçekten ödeyip ödemeyeceğinden emin değilim. Ama sonra, gerçek hayatta hiç VLA kullanmadım, bu yüzden muhtemelen onlar için iyi kullanım durumlarını bilmiyorum.
Johannes Schaub - litb

1
@Ahelps: Belki bunun için en iyi olan şey, bir şekilde davranan vectorancak sabit bir LIFO kullanım modeli gerektiren ve genellikle iş parçacığının sahip olduğu en büyük toplam ayırmaya göre boyutlandırılmış bir veya daha fazla statik olarak ayrılmış arabellek tutan bir tür olabilir. hiç kullanılmamış, ancak bu açıkça kesilmiş olabilir. Normal bir "ayırma" genel durumda bir işaretçi kopyası, işaretçi-işaretçi çıkarma, tamsayı karşılaştırması ve işaretçi eklemesinden başka bir şey gerektirmez; ayırma işlemi basitçe bir işaretçi kopyası gerektirir. Bir VLA'dan çok daha yavaş değil.
supercat

216

(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 xartı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 niçin 1000bir 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 nbir derleme zamanı sabiti olmasaydı (yani, Adeğ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şturabilirizA1Derleme 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, constexpriş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).


15
VLA'ların yanlış olduğunu kabul ediyorum. Çok daha yaygın olarak uygulanan ve çok daha kullanışlı olan, alloca()bunun yerine C99'da standartlaştırılmış olmalıdır. VLA'lar, bir standart komitesi, uygulamaların tersi yerine uygulamalardan önce atladığında gerçekleşir.
Çılgın bilimadamı

10
Değişken değiştirilmiş tip sistemi harika bir IMO'dur ve mermi noktalarınızın hiçbiri sağduyu ihlal etmez. (1) C standardı "derleme zamanı" ile "çalışma zamanı" arasında ayrım yapmaz, bu nedenle bu bir sorun değildir; (2) *isteğe bağlıdır, yazabilirsiniz (ve yazmalısınız) int A[][n]; (3) Tip sistemini herhangi bir VLA bildirmeden kullanabilirsiniz. Örneğin, bir işlev değişken olarak değiştirilmiş tipte dizileri kabul edebilir ve farklı boyutlardaki VLA 2-D olmayan dizilerle çağrılabilir. Ancak yayınınızın ikinci bölümünde geçerli puanlar verirsiniz.
MM

3
"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. Herhangi bir yığın taşması olmadan 2GB'tan daha az bir yığınla bir VLA programı çalıştırdım
Jeff

3
@Jeff: nTest durumunuzdaki maksimum değer neydi ve yığınızın boyutu neydi? nEn az yığınınızın boyutu kadar bir değer girmeyi denemenizi öneririz . (Ve kullanıcının nprogramınızdaki değerini kontrol etmesinin bir yolu yoksa , o zaman maksimum değeri ndoğrudan beyanda int A[1000]yayınlamanızı öneririm : beyan veya ihtiyacınız olan her şey. VLA'lar sadece gerekli ve sadece tehlikeli, maksimum değeri nherhangi bir küçük derleme zamanı sabiti ile sınırlanmadığında.)
Quuxplusone

2
Alloca () bu tür intrinsikler kullanılarak uygulanabildiğinden, tanımı gereği alloca () herhangi bir platformda derleyici standart işlevi olarak uygulanabilmektedir. Derleyicinin ilk alloca () örneğini tespit edememesi ve koda gömülecek işaret ve sürüm türlerini ayarlamamasının bir nedeni yoktur ve bir derleyicinin öbek kullanarak alloca () yığınla yapılamaz. Sert / taşınabilir olmayan şey , bir C derleyicisinin üzerine alloca () uygulanmıştır , böylece çok çeşitli derleyiciler ve işletim sistemleri üzerinde çalışır.
MadScientist

26

İsterseniz, çalışma zamanında yığına bellek ayırmak için her zaman alloca () kullanabilirsiniz:

void foo (int n)
{
    int *values = (int *)alloca(sizeof(int) * n);
}

Yığına tahsis edilmesi, yığın çözüldüğünde otomatik olarak serbest bırakılacağı anlamına gelir.

Kısa not: alloca (3) için Mac OS X kılavuz sayfasında belirtildiği gibi, "alloca () işlevi makineye ve derleyiciye bağımlıdır; kullanımı cesaretsizdir." Sadece biliyorsun.


4
Ayrıca, alloca () kapsamı yalnızca değişkeni içeren kod bloğunun tamamı değil, tüm işlevdir. Bu yüzden bir döngü içinde kullanmak yığını sürekli olarak artıracaktır. Bir VLA'nın bu sorunu yoktur.
sashoalm

3
Bununla birlikte, kapalı blok kapsamına sahip VLA'lar, tüm fonksiyonun kapsamı ile alloca () 'dan önemli ölçüde daha az kullanışlı oldukları anlamına gelir. if (!p) { p = alloca(strlen(foo)+1); strcpy(p, foo); } Şunu düşünün: Bu, tam olarak blok kapsamları nedeniyle VLA'larla yapılamaz.
MadScientist

1
Bu OP'nin neden sorusuna cevap vermiyor . Dahası, bu benzer bir Cçözümdür ve gerçekten- C++değil.
Adrian W

13

Kendi çalışmamda, değişken uzunluklu otomatik diziler veya alloca () gibi bir şey istediğimde, belleğin cpu yığınında fiziksel olarak bulunduğunu umursamadım, sadece genel yığın yavaş geziler yapmaz bazı yığın ayırıcı. Böylece değişken boyutlu arabellekleri itmek / pop bazı bellek sahibi olan bir iş parçacığı nesnesi var. Bazı platformlarda bunun mmu ile büyümesine izin veriyorum. Diğer platformlar sabit bir boyuta sahiptir (genellikle mmu olmadığı için sabit boyutlu bir işlemci yığını ile birlikte gelir). Birlikte çalıştığım bir platformda (avuçiçi bir oyun konsolu) zaten çok az miktarda cpu yığını var, çünkü kıt, hızlı bellekte bulunuyor.

Değişken boyutlu tamponları cpu yığınına itmenin asla gerekli olmadığını söylemiyorum. Dürüst olmak gerekirse, bu kavramın dile yeterince iyi uyduğu gibi göründüğü için standart olmadığını keşfettiğimde şaşırdım. Benim için, "değişken boyut" ve "fiziksel olarak cpu yığınında yer almalıdır" gereksinimleri asla bir araya gelmedi. Hızla ilgili, bu yüzden kendi "veri arabellekleri için paralel yığın" yaptım.


12

Yığın bellek ayırmanın gerçekleştirilen işlemlere göre çok pahalı olduğu durumlar vardır. Bir örnek matris matematiktir. Eğer ufacık matrislerle çalışıyorsanız, 5 ila 10 eleman diyelim ve çok fazla aritmetik yaparsanız, malloc yükü gerçekten önemli olacaktır. Aynı zamanda boyutu derleme zamanı sabit yapmak çok israf ve esnek görünmüyor.

C ++ kendi içinde o kadar güvensiz olduğunu düşünüyorum "argüman daha güvensiz özellikler eklemeye çalışın" çok güçlü değil. Öte yandan, C ++ tartışmasız en çalışma zamanı verimli programlama dili özellikleri olduğundan, bunu her zaman yararlı kılar: Performans açısından kritik programlar yazan kişiler büyük ölçüde C ++ kullanacak ve mümkün olduğunca fazla performansa ihtiyaç duyacaklardır. Bir şeyleri yığından yığına taşımak böyle bir olasılıktır. Öbek bloklarının sayısını azaltmak başka bir şeydir. VLA'lara nesne üyesi olarak izin vermek bunu başarmanın bir yoludur. Böyle bir öneri üzerinde çalışıyorum. Kuşkusuz, uygulanması biraz karmaşıktır, ancak oldukça yapılabilir görünüyor.


12

C ++ 14'te mevcut olacak gibi görünüyor:

https://en.wikipedia.org/wiki/C%2B%2B14#Runtime-sized_one_dimensional_arrays

Güncelleme: C ++ 14'e dönüştürmedi.


ilginç. Herb Sutter burada Dinamik Diziler altında tartışıyor : isocpp.org/blog/2013/04/trip-report-iso-c-spring-2013-meeting (wikipedia bilgisi için referans budur)
Varsayılan

1
"Çalışma zamanı boyutlu diziler ve dynarray, Dizi Uzantıları teknik belirtimine taşındı" yazdı 78.86.152.103 Wikipedia'da 18 Ocak 2014 tarihinde: en.wikipedia.org/w/…
strager

10
Wikipedia normatif bir referans değildir :) Bu teklif C ++ 14'e girmedi.
MM

2
@ViktorSehr: Bu wrt C ++ 17'nin durumu nedir?
einpoklum

@einpoklum Hiçbir fikrim yok boost kullanın: container :: static_vector
Viktor Sehr

7

Bu C ++ / 1x'e dahil edilmek üzere kabul edildi, ancak düştü (bu daha önce söylediğim şey için bir düzeltmedir).

Zaten std::vectorbu rolü doldurmamız gerektiğinden, C ++ 'da daha az yararlı olacaktır .


42
Hayır, yapmıyoruz, std :: vector yığın üzerinde veri ayırmıyor. :)
İstanköy

7
"yığın" bir uygulama detayıdır; derleyici, nesne ömrü garantileri karşılandığı sürece herhangi bir yerden bellek ayırabilir.
MM

1
@MM: Yeterince adil, ama pratikte std::vectordiyelim ki yerine hala kullanamıyoruz alloca().
einpoklum

@einpoklum programınız için doğru çıktı alma açısından yapabilirsiniz. Performans bir uygulama kalitesi sorunudur
MM

1
@MM uygulama kalitesi taşınabilir değildir. ve performansa ihtiyacınız yoksa, ilk etapta c ++ kullanmazsınız
dostum

3

Bunun için std :: vector kullanın. Örneğin:

std::vector<int> values;
values.resize(n);

Bellek yığın üzerinde tahsis edilecektir, ancak bu sadece küçük bir performans dezavantajı taşır. Ayrıca, boyut olarak oldukça sınırlı olduğu için, yığın üzerinde büyük veri blokları tahsis etmemek akıllıca olacaktır.


4
Değişken uzunluklu diziler için önemli bir uygulama, keyfi derece polinomlarının değerlendirilmesidir. Bu durumda, "küçük performans dezavantajı", "tipik durumlarda kodun beş kat daha yavaş çalıştığı" anlamına gelir. Bu küçük değil.
AHelps

1
Neden sadece kullanmıyorsun std::vector<int> values(n);? resizeİnşaattan sonra kullanarak hareket ettirilemez türleri yasaklıyorsunuz.
LF

1

C99, VLA'ya izin verir. Ve VLA'nın nasıl ilan edileceği konusunda bazı kısıtlamalar getiriyor. Ayrıntılar için standardın 6.7.5.2'sine bakın. C ++, VLA'ya izin vermez. Ancak g ++ buna izin verir.


İşaret ettiğiniz standart paragrafa bir bağlantı sağlayabilir misiniz?
Vincent

0

Bunun gibi diziler C99'un bir parçasıdır, ancak standart C ++ 'ın bir parçası değildir. diğerlerinin söylediği gibi, bir vektör her zaman çok daha iyi bir çözümdür, bu yüzden değişken boyutlu diziler C ++ standardında (veya önerilen C ++ 0x standardında) değildir.

BTW, "neden" ile ilgili sorular için C ++ standardı olduğu gibi, yönetilen Usenet haber grubu comp.std.c ++ gidilecek yerdir.


6
-1 Vektör her zaman daha iyi değildir. Genellikle, evet. Her zaman, hayır. Yalnızca küçük bir diziye ihtiyacınız varsa, yığın alanının yavaş olduğu bir platformdaysanız ve kitaplığınızın vektör uygulamasında yığın alanı kullanılıyorsa, bu özellik varsa daha iyi olabilir.
Patrick M

-1

Derleme zamanında değeri biliyorsanız aşağıdakileri yapabilirsiniz:

template <int X>
void foo(void)
{
   int values[X];

}

Düzenle: Ayırıcı bir şablon parametresi olduğundan, yığın ayırıcı (alloca) kullanan bir vektör oluşturabilirsiniz.


18
Derleme zamanında değeri biliyorsanız, hiç bir şablona ihtiyacınız yoktur. X'i doğrudan şablon olmayan işlevinizde kullanın.
Rob Kennedy

3
Bazen arayan derleme zamanında bilir ve arayan bunu yapmaz, şablonlar bunun için iyidir. Tabii ki, genel durumda, hiç kimse X'i çalışma zamanına kadar bilmiyor.
Qwertie

Alloca'yı bir STL ayırıcısında kullanamazsınız - yığın çerçevesi tahrip edildiğinde allocadan tahsis edilen bellek serbest bırakılır - o zaman bellek tahsis etmesi gereken yöntem geri döner.
Oliver

-5

Benim için gerçekten işe yarayan bir çözümüm var. Birçok kez çalışması gereken bir rutin üzerinde parçalanma nedeniyle bellek ayırmak istemedim. Cevap son derece tehlikelidir, bu yüzden kendi sorumluluğunuzda kullanın, ancak yığın üzerinde yer ayırmak için montajdan yararlanır. Aşağıdaki örneğim bir karakter dizisi kullanıyor (açıkçası diğer boyutlu değişkenler daha fazla bellek gerektiriyor).

void varTest(int iSz)
{
    char *varArray;
    __asm {
        sub esp, iSz       // Create space on the stack for the variable array here
        mov varArray, esp  // save the end of it to our pointer
    }

    // Use the array called varArray here...  

    __asm {
        add esp, iSz       // Variable array is no longer accessible after this point
    } 
}

Buradaki tehlikeler çok ama birkaçını açıklayacağım: 1. Değişken boyutunun yarıya kadar değiştirilmesi yığın konumunu öldürür 2. Dizi sınırlarının aşılması diğer değişkenleri ve olası kodu 3 yok eder. Bu 64 bitte çalışmaz build ... bunun için farklı bir montaj gerekir (ancak bir makro bu sorunu çözebilir). 4. Derleyiciye özgü (derleyiciler arasında hareket etmekte sorun olabilir). Denemedim, bu yüzden gerçekten bilmiyorum.


... ve eğer bunu kendiniz yapmak istiyorsanız, belki bir RAII sınıfı mı kullanıyorsunuz?
einpoklum

Sadece boost :: container :: static_vector thou kullanabilirsiniz.
Viktor Sehr

Bu, MSVC'den daha fazla ham montajı olan diğer derleyiciler için eşdeğerlerine sahip değildir. VC muhtemelen espdeğiştiğini anlayacak ve yığınlara erişimini ayarlayacaktır, ancak örneğin GCC'de, en azından optimizasyonları ve -fomit-frame-pointerözellikle kullanıyorsanız, onu tamamen kıracaksınız.
Ruslan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.