2

To loop over a 3x3 array called "a" in C++ i used the following code.

int a[3][3] {};
for(auto &b: a) {
  for(auto &c: b) {
    std::cout << c << std::endl;
  }
}

If I had to replace the "auto", I would intuitively try

int a[3][3] {};
for(int &(b[3]): a) {
  for(int &c: b) {
    std::cout << c << std::endl;
  }
}

But this does not work. Instead I figured out that the following works.

int a[3][3] {};
for(int (&b)[3]: a) {
  for(int &c: b) {
    std::cout << c << std::endl;
  }
}

So the question is: Why does the latter example work?

I thought I needed a reference to an array of length 3, but instead I need an array of length 3 containing references.

5
  • 1
    int (&b)[3] This is a reference to a int[3]. It's a tricky syntax. So you do have a reference to an array of length 3. Commented May 19, 2020 at 11:47
  • 1
    Your "reading" is unfortunately wrong, int &(b)[3] is parsed as an array of references, while int (&b)[3] is a reference to an array of size 3. (see stackoverflow.com/questions/5724171/…) Commented May 19, 2020 at 11:48
  • Because for(int i=0; i<3; i++) for(int j=0; j<3; j++) { std::cout << a[i][j] << std:endl; would have been too readable and simple. So lets try to convolute that fast, readable code into oblivion, C++1x providing all the tools. Bonus points if the machine code also turns slower. Commented May 19, 2020 at 11:55
  • I think int (&b)[3]: a is still way too readable. Do you have any ideas to make it even more unreadable? Commented May 19, 2020 at 12:04
  • 1
    using I3 = int[3]; for(I3 &b: a) { // looks even worse here when I looks like 1. Commented May 19, 2020 at 12:43

2 Answers 2

1

If you have an array like this

T a[N1][N2][N3];

where T is some type specifier and N1, N2, and N3 the sizes of the array then a reference to this array will look like

T ( &ra )[N1][N2][N3]  = a;

If you need to declare a reference to the element of the array that (the element) has the type T[N2][N3] then you can write for example

T ( &e )[N2][N3] = a[0];

Returning to your example you declared an array

int a[3][3] {};

elements of this array have the type int[3]. So to declare a reference to elements of the array you have to write

for ( int ( %row )[3] : a )

As for this declaration

int &(b[3])

(where the parentheses are redundant) then it declares an array of three elements with the type int &. However according to the C++ Standard you may not declare an array of references.

From the C++ Standard (8.3.4 Arrays)

1 In a declaration T D where D has the form

D1 [ constant-expressionopt] attribute-specifier-seqopt

and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is an array type; if the type of the identifier of D contains the auto type-specifier, the program is ill-formed. T is called the array element type; this type shall not be a reference type, the (possibly cvqualified) type void, a function type or an abstract class type....

Sign up to request clarification or add additional context in comments.

Comments

1

int &(b[3]) is equivalent to int & b[3], i.e., an array of references to int whose length is three. This does not correspond to the type of the elements in the array int a[3][3].

The elements in the array int a[3][3] are of type int[3], i.e., an array of int whose length is three. By declaring instead b as int(&b)[3] you declare a reference to such a type.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.