Как я могу получить длину массива, который был передан в функцию? - PullRequest
2 голосов
/ 21 апреля 2020

Учитывая следующую функцию:

template<class T>
void foo(T* ar)
{
    std::cout << sizeof(ar) / sizeof(ar[0]) << std::endl;
    for (int i = 0; i < 6; i++)
        std::cout << ar[i] << " ";
}

И следующий массив:

int ar[] = { 5, 1, 6, 8, 9, 3 };
foo(ar);

Я ожидал, что программа напечатает '6', а затем содержимое массива. Но по какой-то причине sizeof(ar) / sizeof(ar[0]) оценивается как 1 (так как sizeof(ar) и sizeof(ar[0]) оцениваются как '4'), но печать работает нормально (то есть переданный массив содержит все 6 элементов).

Это происходит только с массивами, переданными функциям (я пытался вычислить длину в main (), где был объявлен массив, и он работал нормально). Как я могу получить длину массива внутри функции?

1 Ответ

3 голосов
/ 21 апреля 2020

Просто объявите параметр как имеющий ссылочный тип.

Например

template<class T>
void foo( const T &ar )
{
    size_t n = sizeof(ar) / sizeof(ar[0]);
    std::cout << n << std::endl;
    for (int i = 0; i < n; i++)
        std::cout << ar[i] << " ";
}

Или вы можете использовать следующее объявление

template<class T, size_t N>
void foo( const T ( &ar )[N] )
{
    std::cout << N << std::endl;
    for (int i = 0; i < N; i++)
        std::cout << ar[i] << " ";
}

В противном случае функция имеет дело с указателем. В этом случае вам нужно указать второй параметр, который обозначает длину массива, например

template<class T>
void foo( const T* ar, size_t n )
{
    std::cout << n << std::endl;
    for (int i = 0; i < n; i++)
        std::cout << ar[i] << " ";
}

Поскольку переданный массив не изменяется в функции, соответствующий параметр должен иметь квалификатор const.

Обратите внимание на то, что в стандарте C ++ 17 введена стандартная функция std::size, объявленная в заголовке <iterator>, которую можно использовать вместо выражения sizeof(ar) / sizeof(ar[0])

Таким образом, вы можете написать например, в первой показанной функции

size_t n = std::size(ar)`;
...