3

I'm writing a class which has dynamic two-dimensional array of integers as a field - most imporant part of it, short access time is preferable. I want to declare it in header file,

//Grid.h
class Grid{
  int ** array;
}

however the size and contents of it are yet to be defined in constructor implemented in cpp file (propably a read from ini file).

I'm not sure if declaring a int **array pointer in header and assigning later dynamically array to it with use of

array = new int*[x];  
 for(i=0;i<x;i++){    
array[i] = new int [y];    
}

will result in creating an array that will be accessible and cause no trouble in other functions calling directly to field of array[i][j] in their definitions (or other less obvious errors), however it's granted that before mentioned functions start calling in, it will and has to be defined already.

My question - it this the valid and efficient way to do it? I'll accept any other ideas.
Yes, I've heard of "vector" class but I'm not sure about it's efficiency or read-and-write vs integer array performance. Vectors are flexible in size, but I don't need it - my array once set, will have fixed size.

Propably I'm just too used to Java-style int[][] array code.

1 Answer 1

4

Yes, your way is valid and efficient. Only problem you have (obviously) is to make sure that you don't exceed the limits (Java checks that for you, with C you will have to make sure you are between [0...x-1].

However, if you are speaking of high efficiency, the more efficient way would be to create a one-dimensional array and multiply your way into it. This would be more efficient in terms of memory usage (especially with small sizes) and access time. You could probably wrap the access functions in the grid class (Grid::Set(value, x,y), Grid::Get(x,y)) and check against size overruns yourself.

//Grid.h
class Grid{
    int maxx, maxy;
    int *array;

  public: 
     Grid(int x, int y);
     ~Grid();
     int Get(int x, int y);
}


// making the grid
Grid::Grid(int x, int y) 
{
    this->maxx= x; 
    this->maxy= y;
    this->array= new int[this->maxx*this->maxy];  
}

// destroying the grid
Grid::~Grid() 
{
    this->maxx= this->maxy= 0;
    delete []this->array;  
    this->array= NULL;
}

// accessing the grid
int Grid::Get(int x, int y)
{
#if DEBUG
    assert(x>=0 && x<this->maxx);
    assert(y>=0 && y<this->maxy);
#endif
    return this->array[ y*this->maxx + x];
}
....
Sign up to request clarification or add additional context in comments.

6 Comments

+1 for making the object responsible for access and storage... that is, making the array private and make your Get/Set access methods. That way, you can change your storage implementation and not change the rest of your code. Don't worry about efficiency with access methods... it'll get inlined into your code by the compiler/linker, and if the range check ends up being too pricey you can remove it, again, without changing the rest of your code...
Don't forget the Rule of Three!
Great explanation, thanks. Anbyody cares to explain difference in performance / access times between one and two dimension array?
Your solution needs to fetch the interim pointer to get to the final (2nd dim array). (a) read memory from array with offset x. (b) read memory from result (a) with offset y for actual data. Depending on the size of your arrays, the sub-arrays can be scattered all over the place in memory. The other solution can compute the destination address in registers and has just one memory access. (a) get memory from address array with offset x*y.
Oh, and btw, the speed benefit is marginal unless you do a lot of Grid accesses in tight loops. As initially said, your way is valid and efficient too.
|

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.