0

I took a programming class at university this semester, just out of curiosity. We're doing C++ and I enjoyed it a lot, but the last two weeks have been rather steep for me and heres what troubles my mind:

I'm given a class interface as follows:

class GameOfLife(int rows, int cols);
    public:
        GameOfLife();
        void clear();
        void set(int row, int col, int value);
        void set(int row, int col, const char* values);
        int get(int row, int col);
        void print();
        void advance();
   };

First thing im being asked to do is to implement the constructor so that it allocates memory for a board with the amount of rows and cols passed in the argument. I thought i understood constructors but with this one I'm pretty lost. After i declared int rows and cols in the private section i thought about something along the lines of

GameOfLife::GameOfLife(int x, int y){
    rows = x;
    cols = y;
    board = new int* [rows];

But neither do i know how to handle the second dimension of the board without the compiler yelling at me nor do i know how to test if new memory is actually allocated properly. Any help? :(

Thanks in advance!

  • 3
    `class GameOfLife(int rows, int cols);` at the beginning is wrong, need to move `(int rows, int cols)` inside the constructor. Or is that just some kind of pseudocode? – vsoftco Jan 14 '15 at 00:17

5 Answers5

2

You have to allocate the column array for each row:

  for(int i=0; i<rows; i++)
      board[i] = new int [cols];

If the allocation fails (eg. when you're out of memory), you will get an exception.

Community
  • 1
  • 1
thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
2

In addition to thumbmunkey's correct answer, note that just because the external interface stipulates a 2D array doesn't mean the internal interface has to match.

You could have:

int* board = new int[rows * cols];

Where then instead of get() returning:

return board[x][y];

it would instead be:

return board[x * rows + y];

Sometimes one array is easier to think about than two. Sometimes it's not. Depends on how you want to do it (or if it's stipulated that you have to use one method or the other).

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Out of pure curiosity, could `int*[]` version be faster in the case of access? In the case of `int*`, you have : i) an addition, ii) a multiplication, iii) a dereferencing, whereas for the pointer array `int*[]` just have : i) two dereferencing. Have to say I didn't profile anything though, and probably the compiler optimize the code quite well anyway, so it may not make a visible difference... – vsoftco Jan 14 '15 at 00:23
  • @vsoftco Not even going to wager a guess :) – Barry Jan 14 '15 at 00:25
  • @vsoftco The `int[]` way will allocate less memory though. By `rows * sizeof(int*)` bytes. – Barry Jan 14 '15 at 00:30
  • although `int*[]` is more flexible :) But as you said, it really depends on the task at hand. Although I'll probably try to profile the speed difference (if any). Also, it should be mentioned that your approach is also quite nice whenever you perform operations with the so called "vectorization" of a matrix, i.e reshape it into a vector via appending each row to the previous one (or each column on top of the previous one, depends on the convention). In that case, you already have the vectorized form. Example: trace of A * B will be optimized so it makes use of the vectorized form. – vsoftco Jan 14 '15 at 00:34
0

What you are doing right now with board = new int* [rows]; Is allocating an array of integer pointers. You still need to allocate the memory for the actual integers which is what thumbmunkey is doing with,

for(int i=0;i<rows;i++)
  board[i] = new int [cols];
Community
  • 1
  • 1
kjschiroo
  • 500
  • 5
  • 10
0

There is already a class to dynamically manage memory, it's called vector. If you try to use new in your code then you end up having to reinvent the wheel and write dozens of lines of boilerplate that already exists inside vector.

Also it is simpler to store your board in a contiguous array, there is no need to use a bunch of separate memory blocks to hold the board.

Here is an example:

class GameOfLife
{
public:
    GameOfLife(int rows, int cols);
    void clear();
    void set(int row, int col, int value);
    void set(int row, int col, const char* values);
    int get(int row, int col);
    void print();
    void advance();
private:
    int rows, cols;
    std::vector<int> values;
};

// In the cpp file

GameOfLife::GameOfLife(int rows, int cols)
    : rows(rows), cols(cols), values(rows * cols) {}

void GameOfLife::set(int row, int col, int value)
    { values.at(row * cols + col) = value; }

int GameOfLife::get(int row, int col) 
    { return values.at(row * cols + col); }
M.M
  • 138,810
  • 21
  • 208
  • 365
-1

The essentials - constructor, destructor, getters:

    class GameOfLife
    {
    public:
        GameOfLife(int _rows, int _cols);
        ~GameOfLife ();

        int GetRows () {return rows;}
        int GetCols () {return cols;}
        int **GetBoard () {return board;}

    private:
        int rows, cols;
        int **board;
    };

    GameOfLife::GameOfLife(int _rows, int _cols)
    {
        rows = _rows;
        cols = _cols;
        board = new int *[rows];
        for (int i = 0; i<rows; i++)
            board[i] = new int[cols];
    }

    GameOfLife::~GameOfLife()
    {
        for (int i = 0; i<rows; i++)
            delete [] board[i];
        delete [] board;
    }
IrineK
  • 115
  • 5