При передаче значений массива в функцию компилятор 0 ++ передает только имя массива (адрес, где начинается массив) в функцию . Объясните, почему компилятор C++ передает имя массива в функцию, а не все содержимое массива?Массив, передаваемый функции
ответ
Ваш вопрос неверен. Когда вы пишете
int foo[5] = {1,2,3,4,5};
f(foo);
вы не передаете название foo
функционировать f
, вы передаете указатель на первый элемент foo
. Функция f
знает, что она получает int*
, и она знает, насколько велика int
, поэтому он знает, как далеко впереди в памяти искать второй, третий, четвертый и т. Д. Элементы. Это самый маленький минимум для реализации массивов, поэтому он был популярен.
В C++ 11, чтобы передать массив, который знает, насколько он большой, используйте std::array
. Это массив, который знает, насколько он велик:
#include <array>
std::array<int, 5> foo {1,2,3,4,5};
f(foo);
foo[42] = 1; // compile-time error!
Однако вам нужно написать f
таким образом, что он знает, как большой array
является:
void f(const std::array<int, 5>& ai); // this works
или сделать его шаблонный, поэтому он может принять любой размер массива:
template<size_t Size>
void f(const std::array<int, Size>& ai);
(или даже массив любого типа :)
template<typename T, size_t Size>
void f(const std::array<T, Size>& a);
В качестве альтернативы можно хранить данные в std::vector
. Они иногда менее эффективны, чем std::array
или встроенных массивов, но гораздо более гибким:
std::vector<int> foo {1,2,3,4,5};
f(foo);
...
void f(const std::vector<int>& foo);
«Почему» просто. Потому что это стандарт.
[§4.2 ¶ 1]
Именующее выражение или Rvalue типа «массив из N T» или «массив неизвестного связанного Т» может быть преобразовано в prvalue типа «указатель на T». Применяется временное преобразование материализаций ([conv.rval]) . Результат является указателем на первый элемент массива.
одно имя может использоваться для нескольких различных функций в одном объеме ; это перегрузка функции (пункт [over]). Все декларации для функции должны точно совпадать как с типом возврата, так и с типом-списком параметров типа . Тип функции определяется с помощью следующих правил: . Тип каждого параметра (включая параметры пакетов параметров ) определяется из собственного декларатора decl-specifier-seq и .После определения типа каждого параметра любой параметр типа «массив Т» или типа функции Т устанавливается в «указатель на Т». После создания списка типов параметров любые cv-квалификаторы верхнего уровня, изменяющие тип параметра, удаляются, когда формирует тип функции. Результирующий список преобразованных параметров и наличие или отсутствие эллипсиса или функции пакет параметров - это список параметров параметров функции. [Примечание. Это преобразование не влияет на типы параметров. Например, для
int(*)(const int p, decltype(p)*)
иint(*)(int, const int*)
- это идентичные типы. - примечание к окончанию)
Объяснение того, почему язык определен таким образом, будет трактатом об истории вычислений в целом и языках программирования, в частности, который слишком широк для этого сайта. –