for
with Multidimensional ArraysUnder the new standard we can simplify the previous loop by using a range for
:
size_t cnt = 0;
for (auto &row : ia) // for every element in the outer array
for (auto &col : row) { // for every element in the inner array
col = cnt; // give this element the next value
++cnt; // increment cnt
}
This loop gives the elements of ia
the same values as the previous loop, but this time we let the system manage the indices for us. We want to change the value of the elements, so we declare our control variables, row
and col
, as references (§ 3.2.3, p. 93). The first for
iterates through the elements in ia
. Those elements are arrays of size 4. Thus, the type of row
is a reference to an array of four int
s. The second for
iterates through one of those 4-element arrays. Hence, col
is int&
. On each iteration we assign the value of cnt
to the next element in ia
and increment cnt
.
In the previous example, we used references as our loop control variables because we wanted to change the elements in the array. However, there is a deeper reason for using references. As an example, consider the following loop:
for (const auto &row : ia) // for every element in the outer array
for (auto col : row) // for every element in the inner array
cout << col << endl;
This loop does not write to the elements, yet we still define the control variable of the outer loop as a reference. We do so in order to avoid the normal array to pointer conversion (§ 3.5.3, p. 117). Had we neglected the reference and written these loops as:
for (auto row : ia)
for (auto col : row)
our program would not compile. As before, the first for
iterates through ia
, whose elements are arrays of size 4. Because row
is not a reference, when the compiler initializes row
it will convert each array element (like any other object of array type) to a pointer to that array’s first element. As a result, in this loop the type of row
is int*
. The inner for
loop is illegal. Despite our intentions, that loop attempts to iterate over an int*
.