-1

I am trying to write a class in c++ which will contain a 2D array member variable. The point of the class is to represent a simulated physical model using this array, and I intended to write the various actions I want to perform on the array as member functions.

My problem is trying to initialise the array in the class without hard coding it- ideally, I would like to write the overall program so that the dimension of the array can be inputted by the user at the run time, and this can then be used in the overload constructor for the class. i.e. something like this:


class Lattice{
public:
    //Overload constructor
    Lattice(int);
private:
    //variables:
    int DimensionSize;
    int lattice[DimensionSize][DimensionSize];
}

Lattice::Lattice(int N){
    DimensionSize = N;
    lattice = new int[DimensionSize][DimensionSize];
}

I can see that the code above clearly won't work, as the variable "DimensionSize" is unspecified at runtime, which means the amount of memory required for the 2d array "lattice" is unknown.

I've been looking around on this forum for an answer for this but there doesn't seem to be anything directly helpful for my issue, and any other questions that have been asked seem quite old. If anyone could point me towards a solution, or let me know if what I want is even possible it would be greatly appreciated- I wonder if using a vector instead of an array may be a solution?

Update:

I was able to produce the behaviour that I wanted by using a template class:

template <int N>
class Lattice
{
public:
    //Constructor
    Lattice();
    ~ some other functions ~

private:
    float lattice[N][N];
};

template <int N>
Lattice<N>::Lattice() {
    double rando;
//    Initialise the array to a random state.
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++){
            rando = (double)rand() / ((double)RAND_MAX + 1);
            if( rando <= 0.5 ){
                lattice[i][j] = -1.0;
            }
            else if( rando >= 0.5 ){
                lattice[i][j] = 1.0;
            }
        }
    }
}

I can see using vectors instead of arrays is possible, so my question now is there any major downsides to using a template as above? I can see that the class declaration and definition now have to be contained in the same header file, as outlined in this thread Why can templates only be implemented in the header file? but are there any other problems that may arise apart from this inconvenience?

tam63
  • 191
  • 10
  • 1
    If you need to use dynamic allocation then `int lattice[DimensionSize][DimensionSize];` has to be `int** lattice;` - although it's much better to use a proper container like `std::vector> lattice;` – UnholySheep Apr 01 '20 at 13:00
  • 1
    `std::vector` is the tool for the job, although don't use a 2d one. See this for how you can pretend a have a multi-dimensional vector using a single one: https://stackoverflow.com/questions/43358369/c-n-nested-vectors-at-runtime/43358434#43358434 – NathanOliver Apr 01 '20 at 13:00
  • Possible duplicate of https://stackoverflow.com/questions/936687/how-do-i-declare-a-2d-array-in-c-using-new – iwans Apr 01 '20 at 13:01
  • Yes. The size of an array should be determined at compile-time. What you need is exactly `std::vector` – con ko Apr 01 '20 at 13:01
  • For the template, `size_t` would be more appropriate than `int`. – stark Apr 02 '20 at 12:42

1 Answers1

0

As stated in the comments, if you want to declare a 2D-array and then allocate it with new, declare it like this: int** lattice. Also, i'd recommend declaring it as a single array (or vector), so that all elements are contigous in memory, and then calculate the element-position using x, y and DimensionSize:

class Lattice{
public:
    //Overload constructor
    Lattice(int);
    //access-method
    int getElement(int x, int y)
private:
    //variables:
    int DimensionSize;
    //simple pointer
    int* lattice;
}

Lattice::Lattice(int N){
    DimensionSize = N;
    lattice = new int[DimensionSize*DimensionSize];
}

int Lattice::getElement(int x, int y)
{
    \\calculate the element-position from x and y using DimensionSize
    return lattice[x + y*DimensionSize]; 
}

Since lattice is a private member, you'll have to define an access-method anyways, and having all elements contigous in memory can speed up access quite a bit.

Edit: here is the code with an explicit 2d-array:

class Lattice{
public:
    //Overload constructor
    Lattice(int);
    //access-method
    int getElement(int x, int y)
private:
    //variables:
    int DimensionSize;
    //simple pointer
    int** lattice;
}

Lattice::Lattice(int N){
    DimensionSize = N;
    lattice = new int[DimensionSize][DimensionSize];
}

int Lattice::getElement(int x, int y)
{
    return lattice[x][y]; 
}
melk
  • 530
  • 3
  • 9
  • Thank you for the response- but why is the line `lattice = new int[DimensionSize*DimensionSize];` not: `lattice = new int[DimensionSize][DimensionSize];` as a 2d array is normally initialised? – tam63 Apr 02 '20 at 11:41
  • As i said, declaring it as a single array will cause all elements to be next to each other in memory, and allows you to access them with only one indirection, which makes access faster. But feel free to initalize it as `lattice = new int[DimensionSize][DimensionSize];` if that's clearer for you. – melk Apr 02 '20 at 11:54
  • ah ok, I see what you mean- I think the `int[][]` declaration is necessary for me a the position (i,j) is important for computation of various paramaters that depend on adjectent elements (i + 1, j + 1) etc. Speed of access is important for me though- do you know how significant the speed up is using a 1d array rather than 2d? (It seems a 1d array could be used but it would require a lot of extra code around it...) – tam63 Apr 02 '20 at 12:11