Почему этот цикл "for" не работает?

Рассмотрим:

int ia[3][4];
for (auto row : ia)
        for (auto col : row)

Первый for выполняет итерацию через ia, элементами которой являются массивы размера 4. Потому что row не является ссылкой, когда компилятор инициализирует row, он преобразует каждый элемент массива (как любой другой объект массива type) указателю на первый элемент массива. В результате в этом loop тип row равен int*.

Я не уверен, что понимаю, как работает этот авто, но если я могу предположить, что он автоматически дает тип строке на основе типа элементов массива ia, но я не понимаю, почему этот тип for, где строка не является ссылкой, недействительна. Почему это произойдет? "указатель на этот массив первый элемент", из-за чего?

Ответ 1

Проблема заключается в том, что row является int *, а не a int[4], как можно было бы ожидать, потому что массивы распадаются на указатели, и нет автоматического способа узнать, сколько элементов указывает указатель.

Чтобы обойти эту проблему, std::array был добавлен, где все работает так, как ожидалось:

#include <array>

int main() {
    std::array<std::array<int, 4>, 3> ia;
    for (auto &row : ia){
        for (auto &col : row){
            col = 0;
        }
    }
}

Обратите внимание на & до row и col, которые указывают, что вы хотите ссылку, а не копию строк и столбцов, в противном случае установка col в 0 не повлияет на ia.

Ответ 2

Чтобы предотвратить распад int[] до int*, вы можете использовать &&

int main() {
    int ia[3][4];
    for (auto && row : ia)
        for (auto && col : row)
            ;
}