std::arrayC dizilerinden çok daha üstündür. Eski kodla birlikte çalışmak istesem bile, kullanabilirim std::array::data(). Eski tarz bir dizi istememin bir nedeni var mı?
std::arrayC dizilerinden çok daha üstündür. Eski kodla birlikte çalışmak istesem bile, kullanabilirim std::array::data(). Eski tarz bir dizi istememin bir nedeni var mı?
Yanıtlar:
Bir şeyi gözden kaçırmadıysam (standarttaki en son değişiklikleri çok yakından takip etmedim), C tarzı dizilerin çoğu kullanımı hala devam ediyor. std::arraystatik başlatmaya izin verir, ancak yine de sizin için başlatıcıları saymaz. Ve daha önce C tarzı dizilerin tek gerçek kullanımı std::arrayşu satırlar boyunca statik olarak başlatılmış tablolar içindi:
MyStruct const table[] =
{
{ something1, otherthing1 },
// ...
};
bunların üzerinde yinelemek için olağan beginve endşablon işlevlerini (C ++ 11'de uyarlanmıştır) kullanarak Derleyicinin başlatıcı sayısından belirlediği boyuttan hiç bahsetmeden.
DÜZENLEME: Unuttuğum başka bir şey: dizge değişmezleri hala C tarzı dizilerdir; yani tür ile char[]. Sadece sahip olduğumuz için hiç kimsenin dize değişmezlerini dışlayacağını düşünmüyorum std::array.
const char[]
Hayır. Açıkça söylemek gerekirse. Ve 30 karakterde.
Elbette, uygulamak için C dizilerine ihtiyacınız var std::array, ancak bu, bir kullanıcının C dizilerini istemesi için bir neden değil. Ek olarak, hayır, std::arraybir C dizisinden daha az performansa sahip değildir ve sınır denetimli bir erişim seçeneği vardır. Ve son olarak, herhangi bir C ++ programının Standart kitaplığa bağlı olması tamamen mantıklıdır - bu, standart olma amacının bir çeşididir - ve bir Standart kitaplığa erişiminiz yoksa, derleyiciniz uyumlu değildir ve soru "C ++" olarak etiketlenir, "C ++ ve C ++ olmayanlar, uygunsuz olduğunu düşündükleri için spesifikasyonun yarısını kaçıran şeyler."
std::arrayYine de bağımsız bir C ++ 11 uygulamasında uygulanamayan bir derleyici hakkında ciddi şüphelerim olurdu .
Görünüşe göre çok boyutlu diziler kullanmak C dizilerinden daha kolaydır std::array. Örneğin,
char c_arr[5][6][7];
aksine
std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;
Ayrıca, C dizilerinin otomatik bozunma özelliğinden dolayı c_arr[i], yukarıdaki örnekte bir işaretçi olarak bozulur ve kalan boyutları iki parametre olarak daha geçirmeniz yeterlidir. Demek istediğim o c_arrkopyalamak için pahalı değil. Ancak cpp_arr[i]kopyalamak çok maliyetli olacaktır.
arrayboyutları kaybetmeden çok boyutlu bir işlevi bir işleve geçirebilirsiniz . Ve bunu bir işlev şablonuna aktarırsanız, bu işlev her boyutun hem boyutunu hem de boyutunu veya bunlardan yalnızca birini çıkarabilir. Bu, esas olarak keyfi boyutlar üzerinde çalışan bilimsel şablon kitaplıkları için ilginç olabilir.
template <typename T, int M, int N> using array2d = std::array<std::array<T, N>, M>;bu sorunlardan herhangi birini çözmelidir.
c_arrolduğunu çok kopyalamak için pahalı! Bunu kendiniz yapmak için kodu sağlamalısınız. Bozulacağı işaretçi, bir kopyadan çok referansa daha yakın bir eşdeğerdir ve std::arrayeğer istediğiniz buysa, bir referansı iletmek için kullanabilirsiniz .
std::size_tbunun yerine olması gerekmez intmi? nitpicking için özür dilerim, ama bu onu evrensel yapar.
size_t, ancak 4 milyardan fazla satır veya sütuna sahip dizilerin gerekli olduğu birçok senaryo olduğunu hayal edemiyorum.
Sumant'ın dediği gibi, çok boyutlu dizilerin kullanımı yerleşik C dizileriyle kullanmaktan çok daha kolaydır std::array.
İç içe yerleştirildiğinde, std::arrayokunması çok zor olabilir ve gereksiz yere ayrıntılı hale gelebilir.
Örneğin:
std::array<std::array<int, 3>, 3> arr1;
nazaran
char c_arr[3][3];
Ayrıca, not olduğunu begin(), end()ve size()tüm dönüş anlamsız değerler zaman iç içe std::array.
Bu nedenlerle kendi sabit boyutlu çok boyutlu dizi kaplarımı yarattım array_2dve array_3d. Bunlar benzer olan std::array, ancak 2 ve 3 boyutlu çok boyutlu diziler. Daha güvenlidirler ve yerleşik çok boyutlu dizilerden daha kötü performansları yoktur. Nadir oldukları için boyutları 3'ten büyük olan çok boyutlu diziler için bir kap eklemedim. C ++ 0x'de, keyfi sayıda boyutu destekleyen değişken bir şablon sürümü yapılabilir.
İki boyutlu varyantın bir örneği:
//Create an array 3 x 5 (Notice the extra pair of braces)
fsma::array_2d <double, 3, 5> my2darr = {{
{ 32.19, 47.29, 31.99, 19.11, 11.19},
{ 11.29, 22.49, 33.47, 17.29, 5.01 },
{ 41.97, 22.09, 9.76, 22.55, 6.22 }
}};
Tam dokümantasyon burada mevcuttur:
http://fsma.googlecode.com/files/fsma.html
Kitaplığı buradan indirebilirsiniz:
arr[x][y], arrbir dizi dizisi mi , bir dizi işaretçi mi, bir diziye işaretçi mi yoksa bir işaretçi mi olduğunu söyleyemezsiniz ; tüm uygulamalar, ihtiyaçlarınıza bağlı olarak yasaldır. Ve muhtemelen çok boyutlu diziler için gerçek dünyadaki kullanım durumlarının çoğu, boyutun çalışma zamanında belirlenmesini gerektirir.
C ++ 'da bulunan C tarzı diziler, gerçekte gerçek C dizilerinden çok daha az çok yönlüdür. Aradaki fark, C'de dizi türlerinin çalışma zamanı boyutlarına sahip olabilmesidir . Aşağıdakiler geçerli C kodudur, ancak ne C ++ C tarzı dizilerle ne de C ++ array<>türleriyle ifade edilemez :
void foo(int bar) {
double tempArray[bar];
//Do something with the bar elements in tempArray.
}
C ++ 'da, geçici diziyi öbek üzerinde ayırmanız gerekir:
void foo(int bar) {
double* tempArray = new double[bar];
//Do something with the bar elements behind tempArray.
delete[] tempArray;
}
Bu ile başarılamaz std::array<>çünkübar derleme zamanında bilinmemektedir, bu C ++ veya her iki C tarzı diziler kullanımını gerektirir std::vector<>.
İlk örnek C ++ 'da göreceli olarak kolayca ifade edilebilirken ( new[]ve gerektirse de delete[]), aşağıdakiler C ++' da olmadan elde edilemez std::vector<>:
void smoothImage(int width, int height, int (*pixels)[width]) {
int (*copy)[width] = malloc(height*sizeof(*copy));
memcpy(copy, pixels, height*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y][x] = //compute smoothed value based on data around copy[y][x]
}
}
free(copy);
}
Buradaki nokta, çizgi dizilerinin işaretçilerinin int (*)[width] C ++ 'da bir çalışma zamanı genişliği kullanamamasıdır, bu da herhangi bir görüntü işleme kodunu C ++' da C 'de olduğundan çok daha karmaşık hale getirir: Görüntü işleme örneğinin tipik bir C ++ uygulaması şu şekilde görünür:
void smoothImage(int width, int height, int* pixels) {
int* copy = new int[height*width];
memcpy(copy, pixels, height*width*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
}
}
delete[] copy;
}
Bu kod, yukarıdaki C koduyla tam olarak aynı hesaplamaları yapar, ancak dizin hesaplamasını elle yapması gerekir. indekslerin kullanıldığı her yerde . 2B durum için, bu yine de mümkündür (endeks hesaplamasını yanlış yapmak için birçok fırsatla birlikte gelse de). Yine de, 3B durumunda gerçekten kötü oluyor.
C ++ ile kod yazmayı seviyorum. Ancak ne zaman çok boyutlu verileri değiştirmem gerekse, gerçekten kendime kodun bu bölümünü C'ye taşımam gerekip gerekmediğini soruyorum.
gccörneğin). C11, isteğe bağlı olarak oldukça ilginç şeyler yaptı ve bunun, özelliği yasaklamak istedikleri için olduğunu düşünmüyorum. Bunu, tamamen standart uyumlu bir derleyici yazma düzeyini düşürmek istediklerinin bir işareti olarak görme eğilimindeyim: VLA'ları uygulamak oldukça zor bir canavar ve çoğu kod olmadan da yapılabilir, bu nedenle yeni bir derleyici için yeni bir derleyici için mantıklı geliyor VLA'ları hemen uygulamak zorunda kalmamak için platform.
Olabilir std::arrayyavaş değil. Ama basit depoyu kullanarak bazı kıyaslamalar yaptım ve std :: array; Aşağıdaki karşılaştırma sonuçlarına bakın (W8.1, VS2013 Güncelleme 4'te):
ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;
test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305
Negatif işaretlere göre kullandığım kod pastebin'de ( link )
Kıyaslama sınıf kodu burada ;
Kıyaslamalar hakkında pek bir şey bilmiyorum ... Kodum hatalı olabilir
long test_arr_without_init() { return ARR_SIZE; }
void test_arr_without_init() {}şimdiye çevirebileceği anlamına gelir . Ölçtüğünüz kodun ölçmek istediğiniz kod olduğundan emin olmak için gerçekten çemberlerden geçmeniz gerekir.
std::arraystd::arrayBir C dizisinden nasıl daha az performanslı olacağını söyle .
at()değil operator[], tıpkı gibi std::vector. Performans düşüşü veya kod bloğu yoktur std::array, derleyici bu tür şeyleri optimize etmek için tasarlanmıştır. Ve tabii ki, kontrol edilen fonksiyonun eklenmesi mükemmel bir hata ayıklama aracı ve büyük bir avantajdır. @Lou Franco: Tüm C ++ kodları Standart kitaplığa bağlı olabilir - bunun için olduğu gibi. @Earlz: Kullanılabilir STL'niz yoksa, o zaman C ++ değildir ve bunun sonu budur.
std::arrayeşdeğer C dizisi kullanımından daha büyük olması için çok boktan bir derleyiciye sahip olmalısınız .