Что полезно в отношении параметра reference-to-array?

Недавно я нашел такой код:

typedef int TenInts[10]; void foo(TenInts &arr); 

Что вы можете сделать в теле foo() , которое полезно, что вы не могли сделать, если объявление было:

 void foo(int *arr); // or, void foo(int arr[]); // or, void foo(int arr[10]); // ? 

Я нашел вопрос, который спрашивает, как передать ссылку на массив . Наверное, я спрашиваю, почему .

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

Параметр reference-to-array не позволяет разбить тип массива на тип указателя. т.е. точный тип массива сохраняется внутри функции. (Например, вы можете использовать параметр sizeof arr / sizeof *arr для параметра и получить количество элементов). Компилятор также проведет проверку типов, чтобы убедиться, что тип аргумента массива точно такой же, как тип параметра массива, т. Е. Если параметр объявлен как массив из 10 целых чисел, аргумент должен быть массивом точно равным 10 ints и ничего больше.

Фактически, в ситуациях, когда размер массива фиксирован во время компиляции , использование деклараций параметров reference-to-array (или указатель-массив) может быть воспринято как первичный, предпочтительный способ передать массив. Другой вариант (когда тип массива разрешен для разложения на тип указателя) зарезервирован для ситуаций, когда необходимо передать массивы времени выполнения .

Например, правильный способ передачи массива времени компиляции в функцию

 void foo(int (&arr)[10]); // reference to an array 

или

 void foo(int (*arr)[10]); // pointer to an array 

Несомненно, неправильный способ заключается в использовании «затухающего» подхода

 void foo(int arr[]); // pointer to an element // Bad practice!!! 

«Затухающий» подход обычно резервируется для массивов времени выполнения и обычно сопровождается фактическим размером массива в отдельном параметре

 void foo(int arr[], unsigned n); // pointer to an element // Passing a run-time sized array 

Другими словами, вопрос о «почему» действительно не возникает, когда речь идет о передаче меток-в-массив (или указатель-массив). Вы должны использовать этот метод естественным образом, по умолчанию, когда это возможно, если размер массива фиксирован во время компиляции. Вопрос «почему» должен действительно возникать, когда вы используете «разложившийся» метод передачи массива. «Разложившийся» метод предполагается использовать только как специализированный трюк для передачи массивов времени выполнения.

Вышесказанное в основном является прямым следствием более общего принципа. Когда у вас есть «тяжелый» объект типа T , вы обычно передаете его либо указателем T * либо ссылкой T & . Массивы не являются исключением из этого общего принципа. У них нет причин быть.

Имейте в виду, что на практике часто имеет смысл писать функции, которые работают с массивами времени выполнения, особенно когда речь заходит об общих, библиотечных функциях. Такие функции более универсальны. Это означает, что часто есть веская причина использовать «затухающий» подход в реальном коде жизни. Тем не менее это не позволяет автору кода распознавать ситуации, когда размер массива известен во время компиляции и с использованием ссылки на -абразивный метод соответственно.

Одно отличие состоит в том, что он (предположительно) не может передать нулевую ссылку. Поэтому теоретически функции не нужно проверять, является ли параметр нулевым, тогда как параметр int * arr может быть передан null.

Вы можете написать шаблон функции, чтобы узнать размер массива во время компиляции.

 template size_t array_size(E(&)[size]) { return size; } int main() { int test[] = {2, 3, 5, 7, 11, 13, 17, 19}; std::cout << array_size(test) << std::endl; // prints 8 } 

Нет больше sizeof(test) / sizeof(test[0]) для меня 😉

Вы можете гарантировать, что функция вызывается только для массивов int размером 10. Это может быть полезно с точки зрения проверки типов.

Вы получаете больше семантического значения в отношении ожидаемой функции.

  • Как объявить 2d-массив в C ++ с помощью new?
  • Ошибка создания общего массива
  • Как удалить элемент из массива по значению?
  • Инициализация массива PowerShell
  • Когда имя массива или имя функции «преобразуется» в указатель? (в С)
  • Разница между типом массива и массивом, выделенным с помощью malloc
  • Как скопировать часть массива в другой массив в C #?
  • Можно ли заполнить массив номерами строк, которые соответствуют определенным критериям без цикла?
  • C указатели и массивы / оператор 'sizeof'
  • Сортировка объектов в массиве по дате
  • Является ли массив примитивов Java хранимым в стеке или куче?
  • Давайте будем гением компьютера.