简体   繁体   中英

can't figure out difference between int[3][3] and int(* const)[3]

I have this code:

int board[3][3];        // I am ommiting initialization code for board here so as not to clutter it.
typedef std::vector<std::pair<int [3][3], int> > History;
History hist = History();
const std::pair<int[3][3], int> p = std::make_pair(board, cell);
hist.push_back(p);

but compiling it with g++ gives me this error which I can't understand:

In file included from /usr/include/c++/4.7/bits/stl_algobase.h:65:0,
                 from /usr/include/c++/4.7/vector:61,
                 from performancesystem.h:29:
/usr/include/c++/4.7/bits/stl_pair.h: In instantiation of
    ‘std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = 
    int (*)[3]; _U2 = int; _T1 = int [3][3]; _T2 = int]’:
Test.cpp:74:65:   required from here
/usr/include/c++/4.7/bits/stl_pair.h:111:39: error: incompatible types in
    assignment of ‘int (* const)[3]’ to ‘int [3][3]’

I always had this problem understanding the difference between pointers and arrays in C++. Shouldn't they be the same thing? Can anyone help me please?

The problem in your case is not array-pointer difference (which is big).

The problem is that arrays cannot be by-value-copied in assignment. Wrapping the C array in a class would solve it, or better - use a standard array.

In some situations arrays can be converted to pointers. There is never any conversion the other way around which is what you are trying.

To move forward you should stop using arrays directly. They are fairly useless in C++. I would write a new class (or struct if you prefer)

class Board
{
...
private:
   int sq[3][3];
};

typedef std::vector<std::pair<Board, int> > History;

This way you will stop using useless arrays, and you won't have the confusion over arrays and pointers.

Can't blame you, as the difference of array vs. pointer realizes typically only in dynamically sized structures.

The array int a[3][4][5][6] eg is allocated linearly from memory. It contains 3*4*5*6 units and where a[2][3][4][0] ... a[2][3][4][5] are in 6 consecutive indices and where a[0][1][n][5] are each 6 elements apart and where a[1][n][3][6] are each 5*6 elements apart and so on.

Pointers however provide 'indirection'. The multidimensional array can be implemented by first_level array a[3] providing 3 pointers (indirections) to next level arrays b[4], c[4] and d[4], each of which provide indirection to next level and so on.

In many real life application (eg a table of pointer to strings) one really can't see the difference, as the syntax hides the details:

int main(int ac, char **av) { // one can get third character of third string with av[2][2] , even though the prototype can be represented with int main(int ac, char *av[]); , but not with int main(int ac, char av[][]); as the dimension of the table av can't possibly be determined from that syntax.

The root of the problem is the way in which C and C++ deal with multidimensional arrays. The problems magnify when const is involved.

That std::pair<int [3][3], int> is pair of values, the second of which is an int and the first of which is a pointer to an array of int[3] . That first element is problematic for a number of reasons. One is that it's a pointer. Another is that const does weird things to multidimensional arrays. That's the problem you ran into.

What you want is a 3x3 array as an object. So -- make it an object:

struct Board {
   int arr[3][3];
};

Now your pair becomes std::pair<Board,int> , your vector a std::vector<std::pair<Board, int> > . You can now safely construct a Board , int pair out of local variables because the Board is copied. You couldn't do that safely with raw C multidimensional arrays because that first element would have been a pointer.

Your board defines a constant pointer. The int (* const)[3] is actually the same as a int[n][3] variable: Just a pointer to a array of 3 integers (although the first is a constant one)!
You have three options:

  • Define the T1 in the template as a int (*const)[3]
  • Define the your board as a dynamically allocated array. (with int (*board)[3] = new int[3][3]; )
  • DANGEROUS: const_cast<> your board to a non-const variable. (Better don't do it :D )

LG ntor

PS: However, I would also recommend to write a class for this one and overload the []-operator. Much more state of the art ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM