C + + multidimensional array

Posted by Web For U on Fri, 31 Dec 2021 23:04:12 +0100

Array of arrays

Strictly speaking, there is no multi-dimensional array in C + + language. The commonly mentioned multi-dimensional array is actually an array of arrays. Keeping this in mind will be of great benefit to the understanding and use of multidimensional arrays in the future. When the element of an array is still an array, it is usually defined by two dimensions: one dimension represents the size of the array itself, and the other dimension represents the size of its element (also an array):

void multi_array()
{
    //An array of size 3. Each element is an array containing 4 integers
    int ia[3][4];
    //For an array of size 10, each of its elements is an array of size 20
    //The elements of these arrays are arrays containing 30 integers
    int arr[10][20][30] = {0};
}

Multidimensional array initialization

It is allowed to initialize a multidimensional array with a set of values enclosed in curly braces, just like an ordinary array. In the following initialization form, each row of the multidimensional array is enclosed in curly braces:

void multi_init()
{
    //Three elements, each with a size of 4
    int ia[3][4] = {
        {0, 1, 2, 3},
        {4, 5, 6, 7},
        {8, 9, 10, 11}};
    //You can initialize a two-dimensional array with a curly bracket
    int ib[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    //Displays the first element of each initialization line
    int ic[3][4] = {{0}, {4}, {8}};
    //The first line of initialization is displayed, and other elements are initialized to 0
    int id[3][4] = {0, 3, 4, 6};
}

Subscript access

You can use the subscript operator to access the elements of a multidimensional array. At this time, each dimension of the array corresponds to a subscript operator.

  int arr[3][3][3] = {
        0,
        1,
        2,
    };
    //The first element of arr is used to assign a value to the last element in the last row of ia
    int ia[3][4] = {0};
    ia[2][3] = arr[0][0][0];
    // row is a reference to the ia second element array, containing four elements
    int(&row)[4] = ia[1];

Two nested for loops are often used in programs to deal with the elements of multidimensional arrays

    int ia[rowCnt][colCnt]={0};
 //ergodic
    constexpr size_t rowCnt = 3, colCnt = 4;
    for (size_t i = 0; i != rowCnt; ++i)
    {
        //For each column within a row
        for (size_t j = 0; j != colCnt; ++j)
        {
            //Take the position index of the element as its value
            ia[i][j] = i * colCnt + j;
        }
    }

The range for statement can be used to process multidimensional arrays. Since the range for statement is added in the new C++11 standard, the previous program can be simplified to the following form:

 size_t cnt = 0;
    for (auto &row : ia)
    {
        for (auto &col : row)
        {
            col = cnt++;
        }
    }

Because we want to change the value of array elements, we choose reference types as loop control variables, but there is a deep-seated reason for us to do so. As an example, consider the following loop

  for (auto &row : ia)
    {
        for (auto col : row)
        {
            cout << col << endl;
        }
    }

There is no write operation in this loop, but we still declare the control variable of the outer loop as a reference type to prevent the array from being automatically converted into a pointer. Assuming no reference type is used, the loop is in the following form:

     for (auto row : ia)
    {
        for (auto col : row)
        {
            cout << col << endl;
        }
    }

The program will not compile. This is because, as before, the first loop traverses all the elements of ia, noting that these elements are actually arrays of size 4. Because row is not a reference type, Therefore, when initializing row, the compiler will automatically convert these array elements (like other types of arrays) into pointers to the first element in the array. The type of row obtained in this way is int *. Obviously, the inner loop is illegal. The compiler will try to traverse in an int *, which is obviously far from the original intention of the program.
To use the range for statement to process multidimensional arrays, the control variables of all loops except the innermost loop should be of reference type.

Pointers and multidimensional arrays

When the program uses the name of a multidimensional array, it will also automatically convert it into a pointer to the first element of the array.
When defining a pointer to a multidimensional array, don't forget that the multidimensional array is actually an array of arrays.
Because the multidimensional array is actually an array of arrays, the pointer converted from the multidimensional array name is actually a pointer to the first inner array:

void multi_pointer()
{
    //An array of size 3. Each element is an array containing 4 integers
    int ia[3][4];
    // p points to an array containing four integers
    int(*p)[4] = ia;
    // p points to the tail element of ia
    p = &ia[2];
}

We first make it clear that (* p) means that p is a pointer. Then we look at the right and find that pointer p refers to an array with dimension 4; then we look at the left and know that the elements in the array are integers. Therefore, p is a pointer to an array containing 4 integers.
In the above statement, parentheses are essential:

 //Array of integer pointers
    int *ib[4];
    //Points to an array containing 4 integers
    int(*ib)[4];

With the proposal of the new C++11 standard, adding a pointer type to the array can be avoided as much as possible by using auto or decltype:

 // p points to an array of four integers
    for (auto p = ia; p != ia + 3; ++p)
    {
        // q points to the first element of an array of four integers, that is, q points to an integer
        for (auto q = *p; q != *p + 4; q++)
        {
            cout << *q << ' ';
        }
        cout << endl;
    }

The outer for loop first declares a pointer P and points it to the first inner array of ia, and then iterates successively until all three lines of ia are processed. The increment operation + + P is responsible for moving the pointer p to the next line of ia. The inner for loop is responsible for outputting the values contained in the inner array. It first makes the pointer q point to the first element of the row where p is currently located. * P is an array of four integers. As usual, the array name is automatically converted into a pointer to the first element of the array. The inner for loop iterates until we have processed all the elements of the current inner array. In order to obtain the termination condition of the inner for loop, dereference P again to get the pointer to the first element of the inner array, and add 4 to it to get the termination condition.
Of course, using the standard library functions begin and end can achieve the same function, and it looks more concise:

 // p points to the first array of ia
    for (auto p = begin(ia); p != end(ia); p++)
    {
        // q points to the first element of the inner array
        for (auto q = begin(*p); q != end(*p); q++)
        {
            //Output the integer referred to by q
            cout << *q << ' ';
        }

        cout << endl;
    }

The loop termination condition is determined by the end function. Although we can also infer that the type of p is a pointer to an array containing four integers and the type of q is a pointer to integers, we don't have to worry about what these types are with the auto keyword.

Type aliases simplify pointers to multidimensional arrays

You can define types through keywords such as typedef and using

    // C11 new standard definition type alias
    // int_array is an integer array type that contains four elements
    using int_array = int[4];
    //Equivalent typedef declaration
    // int_array_same is an integer array type that contains four elements
    typedef int int_array_same[4];
    //If you can't define an array type with typedef, you can define an array variable first
    int int_array_inst[4];

If you can't define an array type with typedef, you can define an array variable first

int int_array_inst[4];

Then add typedef

typedef int int_array_inst[4];

At this point int_array_inst is an integer array type of size 4.
Through the type definition, we re implement the traversal

    int ia[3][4];
    //Output the value of each element in ia, and each inner array occupies one row
    for (int_array *p = ia; p != ia + 3; p++)
    {
        for (int *q = *p; q != *p + 4; q++)
        {
            cout << *q << ' ';
        }
        cout << endl;
    }

Topics: C++