Помимо всех распространенных дискуссий о том, когда и как проходить по возможной константной ссылке для непримитивных типов, массивы здесь совершенно особенные.
Из-за обратной совместимости с C, а также из-за вашей конкретной проблемы: массивы могут быть огромными, массивы никогда не передаются по значению ни в C, ни в C ++. Массив затухает в указатель на первый элемент, поэтому, когда вы пишете:
void foo( type array[100] );
Компилятор фактически обрабатывает:
void foo( type *array );
Независимо от того, каков размер массива (здесь есть две распространенные ошибки: полагая, что array
- это массив внутри foo
, и полагая, что в нем будет гарантированно 100 элементов.
Теперь в C ++ вы можете передавать массивы по ссылке, но ссылка должна быть конкретного типа массива, который включает размер:
void foo_array( type (&array)[100] );
Забавный синтаксис говорит компилятору, что функция примет массив из 100 элементов типа type
. Преимущество в том, что компилятор может выполнить проверку размера за вас:
// assuming 'type' is defined
int main() {
type array0[99];
type array1[100];
foo( array0 ); // compiles, but if size=100 is assumed it will probably break
// equivalent to: foo( &array0[0] )
// foo2( array0 ); // will not compile, size is not 100
foo2( array1 ); // compiles, size is guaranteed to be 100
}
Теперь проблема заключается в том, что ваша функция будет работать только для массива точно из 100 элементов, и в некоторых случаях вам может потребоваться выполнить одну и ту же операцию с различными размерами массива. Два решения: шаблонная функция в размере массива, которая обеспечит безопасную по размеру реализацию для каждого используемого размера - большее время компиляции и двоичный размер, шаблон компилируется для каждого другого размера - или с использованием пароля - Синтаксис значения по значению, который сделает распад массива - небезопасным по размеру, который должен быть передан как дополнительный аргумент, меньшее время компиляции и двоичный размер. Третий вариант сочетает в себе оба:
void foo( type *array, int size );
template <size_t N>
void foo( type (&array)[N] ) {
foo( array, N );
}
В этом случае, хотя будет один шаблон foo
для каждого размера, компилятор, скорее всего, встроит вызов, и сгенерированный код будет эквивалентен вызывающей стороне, предоставляющей массив и размер. Никаких дополнительных вычислений не требуется и тип безопасности для реальных массивов.
Теперь передача по ссылке очень редко используется с массивами.