Це насправді дуже важко пояснити, але я підкажу ...
По-перше, dimof
повідомляє вам розмірність або кількість елементів у масиві. (Я вважаю, що "розмірність" є кращою термінологією в програмуючих середовищах Windows).
Це необхідно, тому що C++
і C
не дають вам рідного способу визначення розміру масиву.
Часто люди припускають, що sizeof(myArray)
вони спрацюють, але це фактично надасть вам розмір пам’яті, а не кількість елементів. Напевно, кожен елемент займає більше 1 байта пам'яті!
Далі вони можуть спробувати sizeof(myArray) / sizeof(myArray[0])
. Це дало б розмір в пам'яті масиву, поділене на розмір першого елемента. Це нормально і широко використовується в C
коді. Основна проблема з цим полягає в тому, що воно буде працювати, якщо ви передасте вказівник замість масиву. Розмір вказівника в пам'яті зазвичай становитиме 4 або 8 байт, навіть якщо річ, на яку він вказує, може бути масивом з 1000-ти елементів.
Отже, наступне, що потрібно спробувати, C++
- це використовувати шаблони, щоб змусити щось, що працює лише для масивів, і дасть помилку компілятора на покажчик. Це виглядає приблизно так:
template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"
Шаблон працюватиме лише з масивом. Він виведе тип (не дуже потрібен, але повинен бути там, щоб шаблон запрацював) та розмір масиву, після чого він поверне розмір. Спосіб написання шаблону не може працювати з покажчиком.
Зазвичай ви можете зупинитися тут, і це в Стандартній бібліотеці C ++ як std::size
.
Попередження: внизу тут він потрапляє на волохату мову-адвокатську територію.
Це дуже круто, але все ж не вдається в незрозумілому краєвому випадку:
struct Placeholder {
static float x[8];
};
template <typename T, int N>
int ArraySize (T (&)[N])
{
return N;
}
int main()
{
return ArraySize(Placeholder::x);
}
Зверніть увагу , що масив x
буде оголошений , але не визначено . Щоб викликати функцію (тобто ArraySize
) з нею, x
необхідно визначити .
In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status
Ви не можете зв’язати це.
Код, який ви маєте у запитанні, є способом цього подолати. Замість того, щоб насправді викликати функцію, ми оголошуємо функцію, яка повертає об’єкт точно потрібного розміру . Тоді ми використовуємо sizeof
фокус на цьому.
Це виглядає , як ми називаємо функцію, але sizeof
це чисто час компіляції конструкт, тому функція фактично ніколи не викликається.
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
Зауважте, ви фактично не можете повернути масив з функції, але ви можете повернути посилання на масив.
Тоді DimofSizeHelper(myArray)
це вираз , чий тип є масивом на N
char
с. Вираз насправді не повинен бути досяжним, але це має сенс під час компіляції.
Тому sizeof(DimofSizeHelper(myArray))
підкаже вам розмір за час компіляції того, що ви отримали, якби ви насправді викликали функцію. Незважаючи на те, що ми насправді не називаємо це.
Не хвилюйтесь, якщо цей останній блок не мав сенсу. Це химерний трюк, щоб обходити справу з химерним краєм. Ось чому ви не пишете такий код самостійно, а дозвольте виконавцям бібліотек хвилюватися з приводу такої дурниці.
std::array
абоstd::vector
....