Bu aslında açıklanması gerçekten zor bir şey ama ben bir deneyeceğim ...
İlk olarak, bir dizideki öğelerin boyutunu veya öğelerini dimof
söyler . ("Boyut" un Windows programlama ortamlarında tercih edilen terminoloji olduğuna inanıyorum).
Bu gereklidir, çünkü C++
ve C
size bir dizinin boyutunu belirlemek için bir yerli yol vermeyin.
Çoğu zaman insanlar sizeof(myArray)
işe yarayacağını varsayarlar , ancak bu aslında öğelerin sayısından ziyade hafızadaki boyutu verecektir. Her öğe muhtemelen 1 bayttan fazla bellek alır!
Sonra deneyebilirler sizeof(myArray) / sizeof(myArray[0])
. Bu, dizinin belleğindeki boyutu, ilk öğenin boyutuna böler. Tamam ve C
kodda yaygın olarak kullanılır . Bununla ilgili en büyük sorun, bir dizi yerine bir işaretçi iletirseniz işe yarayacağıdır. İşaret ettiği şey 1000'er elementlik bir dizi olsa da, bellekteki bir işaretçinin boyutu genellikle 4 veya 8 bayt olacaktır.
Denemek için bir sonraki şey C++
, sadece diziler için çalışan ve bir işaretçi üzerinde bir derleyici hatası verecek bir şeyi zorlamak için şablonlar kullanmaktır. Şöyle görünüyor:
template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"
Şablon yalnızca bir dizi ile çalışır. Tür (gerçekten gerekli değildir, ancak şablonun çalışması için orada olması gerekir) ve dizinin boyutunu çıkarır, sonra boyutu döndürür. Şablonun yazılma şekli bir işaretçi ile çalışamaz.
Genellikle burada durabilir ve bu C ++ Standart Libary'de olduğu gibi std::size
.
Uyarı: burada aşağıda kıllı dil-avukat topraklarına giriyor.
Bu oldukça havalı, ancak hala belirsiz bir kenar durumunda başarısız oluyor:
struct Placeholder {
static float x[8];
};
template <typename T, int N>
int ArraySize (T (&)[N])
{
return N;
}
int main()
{
return ArraySize(Placeholder::x);
}
Dizi unutmayın x
edilir ilan , ancak tanımlanmış . Bir işlevi (yani ArraySize
) onunla çağırmak x
için tanımlanmalıdır .
In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status
Bunu bağlayamazsınız.
Soruda bulunan kod bunun bir yoludur. Bir işlevi gerçekten çağırmak yerine, tam olarak doğru boyutta bir nesne döndüren bir işlev beyan ederiz . Sonra bu konuda sizeof
hileyi kullanıyoruz .
O görünüyor biz işlevi çağırmak gibi ama sizeof
işlevi gerçekte hiçbir zaman çağrılır, böylece tamamen bir derleme zamanı yapıdır.
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
^^^^ ^ ^^^
// a function that returns a reference to array of N chars - the size of this array in memory will be exactly N bytes
İşlevden bir dizi döndüremeyeceğinizi, ancak bir diziye başvuru döndürebileceğinizi unutmayın.
Sonra türü s'de bir dizi olan DimofSizeHelper(myArray)
bir ifadedir . İfadenin aslında çalıştırılabilir olması gerekmez, ancak derleme zamanında mantıklıdır.N
char
Bu nedenle , işlevi gerçekten çağırırsanız ne elde edeceğinizin derleme zamanında boyutunusizeof(DimofSizeHelper(myArray))
söyleyecektir . Aslında aramamıza rağmen.
Bu son blokun bir anlamı yoksa endişelenmeyin. Tuhaf bir kenar kasasının etrafında çalışmak garip bir numara. Bu yüzden bu tür bir kodu kendiniz yazmazsınız ve kütüphane uygulayıcılarının bu tür saçmalıklar hakkında endişelenmesine izin vermezsiniz.
std::array
std::vector