Неопределенный размер массива в параметре функции - PullRequest
0 голосов
/ 06 апреля 2019

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

Ответы [ 2 ]

1 голос
/ 06 апреля 2019

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

Типы массивов в сигнатурах функций на самом деле являются указателями.Все следующие три объявления абсолютно одинаковы:

void foo(int a[10]);
void foo(int a[]);
void foo(int* a);

Во всех трех случаях foo принимает один параметр: указатель на int.Когда вы передаете массив этой функции, он неявно распадается на указатель на свой первый элемент.

Когда массив распадается на указатель, длина массива теряется.Это означает, что следующий код скомпилируется, но логически неверен:

void foo(int a[10]) {
    for (size_t i = 0; i < 10; ++i) {
        std::cout << a[i] << '\n';
    }
}

int main() {
    // Whoops, wrong size array!
    int arr[5] = {};
    foo(arr);
}

Live Demo

Объявление длины, в данном случае, является полной и полной ложью,Запись бессмысленного числа в определении функции просто увеличивает риск того, что кто-то допустит ошибку.


Если вы должны использовать необработанные указатели для параметра функции, принимающего массив, ваша функция также должна принять параметр размера:

void foo(int* a, size_t length) {
    for (size_t i = 0; i < length; ++i) {
        std::cout << a[i] << '\n';
    }
}

int main() {
    int arr[5] = {};
    foo(arr, 5);
}

Live Demo

Это также опасно, так как кто-то может полностью пропустить неправильный размер и вызвать ошибки:

void foo(int* a, size_t length) {
    for (size_t i = 0; i < length; ++i) {
        std::cout << a[i] << '\n';
    }
}

int main() {
    int arr[5] = {};
    //Whoops, passed the wrong size!
    foo(arr, 10);
}

Live Demo

По этой причине вы должны предпочесть использовать контейнер:

void foo(const std::vector<int>& a) {
    for (int i : a) {
        std::cout << i << '\n';
    }
}

int main() {
    std::vector<int> arr(5);
    foo(arr);
}

Live Demo

Если вы не знаете, какой тип контейнера использовать;по умолчанию std::vector.Если ваша функция должна поддерживать несколько типов контейнеров, используйте шаблон:

template <typename Container>
void foo(const Container& a) {
    for (int i : a) {
        std::cout << i << '\n';
    }
}

int main() {
    std::vector<int> arr(5);
    foo(arr);
    std::array<int, 5> arr2 = {};
    foo(arr2);
}

Live Demo

0 голосов
/ 06 апреля 2019

Конечно, вы можете указать (фиксированный) размер массива в качестве параметра функции - вы должны передать массив по ссылке.

void func(int (&x)[100]);

передает массив типа int размером 100.

Вы могли бы даже сделать шаблон для него

template<class T, size_t N> void func(T (&x)[N]) {...}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...