Почему нельзя передавать массивы в качестве аргументов функции?
Они могут:
void foo(const int (&myArray)[5]) {
// `myArray` is the original array of five integers
}
В технических терминах тип аргумента для foo
является "ссылкой на массив из 5 const
int
s";со ссылками мы можем передать фактический объект вокруг ( отказ от ответственности : терминология зависит от уровня абстракции) .
Что вы не можете сделатьпередается значением , потому что по историческим причинам мы не будем копировать массивы.Вместо этого, попытка передать массив по значению в функцию (или передать копию массива) приводит к тому, что его имя затухает в указателе. ( некоторые ресурсы ошибаются! )
Имена массивов затухают в указателях для передачи по значению
Это означает:
void foo(int* ptr);
int ar[10]; // an array
foo(ar); // automatically passing ptr to first element of ar (i.e. &ar[0])
Существует также чрезвычайно вводящий в заблуждение "синтаксический сахар", который выглядит , как будто вы можете передать массив произвольной длины по значению:
void foo(int ptr[]);
int ar[10]; // an array
foo(ar);
Но, на самом деле,вы все еще просто передаете указатель (на первый элемент ar
).foo
- это то же самое, что и выше!
Пока мы на нем, следующая функция также на самом деле не имеет такой подписи, как кажется.Посмотрите, что происходит, когда мы пытаемся вызвать эту функцию, не определяя ее:
void foo(int ar[5]);
int main() {
int ar[5];
foo(ar);
}
// error: undefined reference to `func(int*)'
Итак, foo
фактически принимает int*
, не int[5]
!
( Live демо. )
Но вы можете обойти это!
Вы можете взломать это , обернув массивв struct
или class
, поскольку оператор копирования по умолчанию будет копировать массив:
struct Array_by_val
{
int my_array[10];
};
void func (Array_by_val x) {}
int main() {
Array_by_val x;
func(x);
}
Это несколько запутанное поведение.
Или, лучше, общий подход с передачей по ссылке
В C ++ с помощью некоторой магии шаблонов мы можем сделать функцию как многократно используемой, так и получающей массив:
template <typename T, size_t N>
void foo(const T (&myArray)[N]) {
// `myArray` is the original array of N Ts
}
Но мы все еще не можем передать один по значению.Что-то, что нужно помнить.
Будущее ...
И поскольку C ++ 11 уже не за горами, а поддержка C ++ 0x идет хорошо в основных инструментальных цепочкахВы можете использовать прекрасный std::array
унаследованный от Boost!Я оставлю исследование этого в качестве упражнения для читателя.