C++ 2D arrays

Started by
32 comments, last by Cacks 18 years, 8 months ago
Hi guys, got a problem creating a 2D array in C++. I want to declare a pointer to the 2D array in my header, then when initializing an object allocate the memory for it. I want to do something like this: //Header bool spaces[][]; //.cpp file spaces = new bool[width][height]; OR Maybe //Header bool* spaces; //.cpp file spaces = new bool[width][height]; ?? This seems like it should be easy, what am I doing wrong? Thanks for any help!
Reject the basic asumption of civialisation especially the importance of material possessions
Advertisement
What's the problem? Errors? Crash?
My program won't compile & gives the following errors;

1. non-constant expression as array bound

2. error C2440: '=' : cannot convert from 'bool (*)[1]' to 'bool * '
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style
cast or function-style cast
Reject the basic asumption of civialisation especially the importance of material possessions
What data types are your width and height indexers?
This is a complicated thing but this is how you do it:

		bool (* spaces)[10];		spaces = new bool[10][10];


ace
They are both ints

For example, the following lines;

int* arr = new int[12]; - Is OKAY
int* arr = new int[12][12]; - NOT OKAY

Any ideas?
Reject the basic asumption of civialisation especially the importance of material possessions
The above that i posted works.

ace
There is no operator new[][] in C++ - it is limited to 1D arrays.

There are a couple ways to go about what you're attempting in C++. First, the ugly way, is to create a 1D array of pointers to 1D arrays (or in ace_lovegrove's example, a 1D array of 1D arrays of fixed size) like so:

//allocation:int ** foo;foo = new int * [width];for ( int x = 0 ; x < width ; ++x ) {    foo[x] = new int[ height ];}//use:foo[x][y] = 13;//deallocation:for ( int x = 0 ; x < width ; ++x ) {    delete[] foo[x];}delete[] foo;


One could convert the above example to something easier to clean up by using std::vector, of course, like so:
#include <vector>std::vector< std::vector< int > > foo;for ( foo int x = 0 ; x < width ; ++x ) {    foo[x].resize( height );}//use:foo[x][y] = 13;//deallocation is automatic when foo goes out of scope


Finally, there's boost::multi_array, a fine part of the Boost C++ Libraries:
#include <boost/multi_array.hpp>//allocation:boost::multi_array< int , 2 > foo( boost::extents[width][height] ); //2 = two dimentions//use:foo[x][y] = 13;//deallocation is automatic when foo goes out of scope


Out of these three examples, I'd suggest the last. The boost library collection has many excellent tools, and it is well worth installing.
Only the outermost array dimension can be left unspecified.

In other words, while an array a[row][col] can have as many rows as you want, you must tell the compiler how many columns it has, otherwise it cannot compute the offset necessary to go from one line to the next.

So in your case bool spaces[][height] is the best you can get, short of manually allocating an array of arrays.

Save yourself some trouble, use a std::vector with manual 2D-indexing index = row*rowsize + col or go use boost::multi_array.

edit: What MaulingMonkey said.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
You can only dynamically allocate one dimension at a time. You have three options:

  1. Allocate the first dimension as a sequence of pointers, then allocate the second dimension to each pointer. This has interesting memory characteristics and pointer arithmetic semantics.
    int ** arr2d = new int * [length];for (int n = 0; n < length; ++n)  arr2d[n] = new int [height];

    You have to deallocate in reverse order:
    for (int n = 0; n < length; ++n)  delete [] arr2d[n];delete [] arr2d;

  2. Allocate the entire block linearly, then use either pointer arithmetic or other skullduggery to simulate native 2D semantics.
    int index2d(int x, int y){  return y * height + x;}...int * real_arr2d = new int [length * height];real_arr2d[index2d(1, 1)] = 5;

  3. Use nested std::vector.
    vector< vector<int> > arr2d;arr2d.reserve(length);for (int n = 0; n < length; ++n){  vector<int> v(height)  arr2d.push_back(v);}


[Edit: whoops! Forgot std::vector...]

This topic is closed to new replies.

Advertisement