Интересно, почему этот вид кода может получить размер тестового массива? Я не знаком с грамматикой в шаблоне. Может быть, кто-то может объяснить смысл кода ниже template<typename,size_t>
. Кроме того, ссылка ссылка также предпочтительнее.
#define dimof(array) (sizeof(DimofSizeHelper(array)))
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
void InitDynCalls()
{
char test[20];
size_t n = dimof(test);
printf("%d", n);
}
c++
visual-c++
Тень
источник
источник
std::array
илиstd::vector
....Ответы:
Это на самом деле очень сложно объяснить, но я попробую ...
Во-первых,
dimof
сообщает вам размер или количество элементов в массиве. (Я считаю, что «измерение» является предпочтительной терминологией в средах программирования Windows).Это необходимо, потому что
C++
иC
не дает вам собственного способа определения размера массива.Часто люди предполагают, что
sizeof(myArray)
это сработает, но на самом деле это даст вам размер в памяти, а не количество элементов. Каждый элемент, вероятно, занимает более 1 байта памяти!Далее они могут попробовать
sizeof(myArray) / sizeof(myArray[0])
. Это даст размер в памяти массива, деленный на размер первого элемента. Это нормально и широко используется вC
коде. Основная проблема заключается в том, что он будет работать, если вы передадите указатель вместо массива. Размер указателя в памяти обычно составляет 4 или 8 байт, даже если он указывает на массив из 1000 элементов.Итак, следующая вещь, которую
C++
стоит попробовать - это использовать шаблоны для принудительного использования чего-то, что работает только для массивов и будет давать ошибку компилятора в указателе. Это выглядит так:Шаблон будет работать только с массивом. Он выведет тип (не очень необходимый, но должен присутствовать, чтобы шаблон работал) и размер массива, а затем вернет размер. Способ написания шаблона не может работать с указателем.
Обычно вы можете остановиться здесь, и это в C ++ Standard Libary as
std::size
.Внимание: ниже здесь он попадает на волосатую языковую территорию юриста.
Это довольно круто, но все равно не получается в неясном случае:
Обратите внимание , что массив
x
будет объявлен , но не определен . Чтобы вызвать функцию (то естьArraySize
) с ней,x
должна быть определена .Вы не можете связать это.
Код, который у вас есть в вопросе, помогает обойти это. Вместо того, чтобы фактически вызывать функцию, мы объявляем функцию, которая возвращает объект точно правильного размера . Тогда мы используем
sizeof
трюк на этом.Это выглядит , как мы называем функцию, но
sizeof
это чисто время компиляции конструкт, поэтому функция фактически никогда не вызывается.Обратите внимание, что вы на самом деле не можете вернуть массив из функции, но вы можете вернуть ссылку на массив.
Тогда
DimofSizeHelper(myArray)
это выражение , тип которого является массивом наN
char
s. Выражение на самом деле не обязательно должно выполняться, но оно имеет смысл во время компиляции.Поэтому
sizeof(DimofSizeHelper(myArray))
вам сообщат размер во время компиляции того, что вы получите, если бы вы действительно вызвали функцию. Хотя мы на самом деле не называем это.Не волнуйтесь, если последний блок не имеет никакого смысла. Это странный трюк, чтобы обойти причудливый крайний случай. Вот почему вы сами не пишете такого рода код, и позволяете разработчикам библиотек беспокоиться о такой ерунде.
источник
DimofSizeHelper
это шаблонная функция, которая принимаетT(&)[N]
параметр - он же ссылка на C-массив из N элементов типаT
и возвращаетchar (&)[N]
aka ссылку на массив из N символов. В C ++ символ является замаскированным байтом иsizeof(char)
гарантированно1
соответствует стандарту.n
присваивается размер возвращаемого типаDimofSizeHelper
,sizeof(char[N])
который естьN
.Это немного запутанно
и ненужный, Обычный способ сделать это было:Начиная с C ++ 17 это также не нужно, поскольку у нас
std::size
есть такая возможность, но в более общем смысле, возможность получить размер любого контейнера в стиле stl.Как указывает BoBTFish, это необходимо для крайнего случая.
источник
std::extent
с C ++ 11, время компиляции.