2016-12-18 3 views
-1

При передаче значений массива в функцию компилятор 0 ++ передает только имя массива (адрес, где начинается массив) в функцию . Объясните, почему компилятор C++ передает имя массива в функцию, а не все содержимое массива?Массив, передаваемый функции

+0

Объяснение того, почему язык определен таким образом, будет трактатом об истории вычислений в целом и языках программирования, в частности, который слишком широк для этого сайта. –

ответ

0

Ваш вопрос неверен. Когда вы пишете

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); 
1

«Почему» просто. Потому что это стандарт.

[§4.2 ¶ 1]

Именующее выражение или Rvalue типа «массив из N T» или «массив неизвестного связанного Т» может быть преобразовано в prvalue типа «указатель на T». Применяется временное преобразование материализаций ([conv.rval]) . Результат является указателем на первый элемент массива.

[§8.3.5 ¶ 5]

одно имя может использоваться для нескольких различных функций в одном объеме ; это перегрузка функции (пункт [over]). Все декларации для функции должны точно совпадать как с типом возврата, так и с типом-списком параметров типа . Тип функции определяется с помощью следующих правил: . Тип каждого параметра (включая параметры пакетов параметров ) определяется из собственного декларатора decl-specifier-seq и .После определения типа каждого параметра любой параметр типа «массив Т» или типа функции Т устанавливается в «указатель на Т». После создания списка типов параметров любые cv-квалификаторы верхнего уровня, изменяющие тип параметра, удаляются, когда формирует тип функции. Результирующий список преобразованных параметров и наличие или отсутствие эллипсиса или функции пакет параметров - это список параметров параметров функции. [Примечание. Это преобразование не влияет на типы параметров. Например, для int(*)(const int p, decltype(p)*) и int(*)(int, const int*) - это идентичные типы. - примечание к окончанию)