std::array
C 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::array
C 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::array
statik 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 begin
ve 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::array
bir 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::array
Yine 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_arr
kopyalamak için pahalı değil. Ancak cpp_arr[i]
kopyalamak çok maliyetli olacaktır.
array
boyutları 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_arr
olduğ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::array
eğer istediğiniz buysa, bir referansı iletmek için kullanabilirsiniz .
std::size_t
bunun yerine olması gerekmez int
mi? 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::array
okunması ç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_2d
ve 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]
, arr
bir 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::array
yavaş 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::array
std::array
Bir 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::array
eşdeğer C dizisi kullanımından daha büyük olması için çok boktan bir derleyiciye sahip olmalısınız .