Я пытаюсь изучать C ++, но я просто не могу обдумать этот код здесь, несмотря на то, что трачу много времени на поиск ответа:
#include <iostream>
void printArray1(int (&array)[3]) {
for(int x : array)
std::cout << x << " ";
}
void printArray2(int array[]) {
for(int x : array) // compiler error, can't find begin and end
std::cout << x << " ";
}
int main() {
int a[3] = {34,12,88};
for(int x : a)
std::cout << x << " ";
std::cout << std::endl;
printArray1(a);
printArray2(a);
std::cout << std::endl;
return 0;
}
В printArray1 мы получаем параметр, который является ссылкой на массив размера 3. Означает ли это, что мы получаем адрес всего массива или мы просто получаем адрес первого элемента в массиве размера 3? Кроме того, как этот параметр затем передается в цикл?
В printArray2 мы получаем указатель на первый элемент в массиве, правильно? Другими словами, мы также получаем адрес, как в printArray1? Таким образом, циклический цикл for в этой функции не будет компилироваться, потому что у нас нет данных о размере массива, верно?
Наконец, когда мы пытаемся печатать с помощью цикла for на основе ранжирования в main, что именно мы передаем в цикл? Это указатель на первый элемент в массиве, и если так, почему он компилируется, если цикл for в printArray2 не принимает указатель?
Мое понимание C ++ все еще довольно элементарно, поэтому я действительно ценю помощь, спасибо!
Циклический цикл for работает для всех типов, которые можно использовать с std::begin
а также std::end
,
Массивы и указатели не совпадают. Массив имеет фиксированный размер, указатель — нет. следовательно std::begin
а также std::end
работать для массивов — но не для указателей. Это также объясняет, почему основанный на диапазоне цикл for работает для одного, но не для другого.
Массивы также могут распадаться на указатели. Это происходит, например, когда передается функциям, которые принимают параметр указателя. Или, когда передается функциям, которые принимают параметр массива неопределенного размера (который фактически совпадает с параметром указателя). Когда это происходит, информация о размере снова теряется.
Так что это зависит от того, как вы определяете функцию. Первая функция принимает массив, вторая — указатель. Вот почему первый сохраняет информацию о размере, и цикл работает.
Однако это ограничивает возможности функции. Вторая функция может взять int b[2]
пока первое не может.
в [3]
В этом случае функция знает, насколько велик массив по своему типу. Ссылка часто реализуется как указатель на упомянутую вещь, но в C ++ пройдена большая длина, чтобы оставить эту деталь реализации (которая иногда позволяет оптимизировать). Рекомендации псевдонимы для данных в другом месте, немного отличается от указателей (которые похожи на почтовые адреса). Итерация проста, когда компилятор имеет длину, а C ++ делает правильные вещи.
в []
случай, это синтаксис в стиле C. Это не ссылка. Это означает так же, как int * array
, Размер массива не является ни типом времени компиляции (в функции), ни состоянием времени выполнения (который является одним указателем типа int). Очевидно, итерация невозможна без длины.
Согласно cppreference о массивы а также Ранжированный для цикла
В printArray1, массив аргумент представляет собой массив INT ссылки каждый из которых будет ссылаться на первые 3 значения массива, передаваемого в качестве аргумента.
В printArray2, массив Аргумент — это указатель, который указывает на первое значение массива, переданного в качестве аргумента. С его помощью вы можете получить доступ ко всем значениям массива.
Наконец, это не указатель, а просто ссылка на массив.
В этом конкретном случае важно знать, что для каждой итерации копия итерированного значения будет выполняться для Икс переменная.
Если вы хотите предотвратить появление всех этих копий, вы должны объявить ссылку.
Пример:
for(int &x : a)
std::cout << x << " ";
Кстати, вы также должны взглянуть на контейнер массива, который является массивом в современном стиле.