0

Suppose that I have a class like this one:

class SpinSystem{
private:
  int L;
  int L2;
  const int k=1, J=1;
  const int teq, tcorr;
  const double TC=2/log(1+sqrt(2.0));//TC=2.269;
  double Temp;
  int Nmuestras;
  int s[L][L]; int E,M; 
  int Cluster[L2][2]; int write;
public:
  void set_values(int, double, int);
};

void SpinSystem::set_values(int length, double temperature, int nsamples){
  L = length;
  Temp = temperature;
  Nmuestras = nsamples;
  L2 = length*length;
  teq = (int)(10*pow(length/8.0,0.58));
  tcorr = (int)(1*pow(length/8.0,0.58));
}

The private variables L2, teq, tcorr depend on the value of L. This is why I set their values with the method set_values. However, I have to define some arrays, such as s[L][L] and Cluster[L2][2], whose sizes clearly depend on L. How can I achieve this? Thanks in advance.

Vladimir Vargas
  • 1,744
  • 4
  • 24
  • 48
  • You need to allocate (and free) the memory dynamically. See keyword new, then once you understand use a unique_ptr so you don't forget to free it. – djgandy Aug 23 '17 at 15:56
  • 2
    Use a `std::vector`? – crashmstr Aug 23 '17 at 15:59
  • Best SO post I found - https://stackoverflow.com/questions/936687/how-do-i-declare-a-2d-array-in-c-using-new . Grid solution is perfect for preserving C-like behaviour and preserving linear memory space. – djgandy Aug 23 '17 at 16:20

2 Answers2

2

You should handle all this in a constructor; init functions have all kinds of associated problems. And you should ensure that variables are listed in dependency order (i.e. if one variable depends on another, the latter must be declared first). Also, fixed constants can simply be made static as they are always the same. You don't need to keep variables that are trivially derived from others like L2. Initialize things inline when you can.

class SpinSystem{
private:
  static constexpr int k=1;
  static constexpr int J=1;
  static constexpr double TC=2/log(1+sqrt(2.0));//TC=2.269;

  int teq = (int)(10*pow(length/8.0,0.58));
  int tcorr = (int)(1*pow(length/8.0,0.58));

  int L;
  double Temp;
  int Nmuestras;

  std::vector<int> s;
  int E;
  int M;
  std::vector<int> Cluster;
  int write;
public:
  void SpinSystem(int length, double temp, int nsamples)
    : L(length)
    , Temp(temp)
    , NMmuestras(nsamples)
  {
    s.resize(L*L);
    Cluster.resize(L*L*2);
  }
};

Here I create one dimensional arrays of the same total size. I strongly recommend you just do that and use a simple function to convert the index as you need to. But if you don't like that you can always have nested vectors.

Make sure in your real code to initialize E, M, and Write... preferably inline or in the initializer list.

Nir Friedman
  • 17,108
  • 2
  • 44
  • 72
  • Why not add `s` and `Cluster` to your init list? `... , NMmuestras(nsamples), s(L*L), Cluster(L*L*2) {}` – Robᵩ Aug 23 '17 at 16:35
  • @Rob I suppose you could, I'm just in the habit because calling `reserve` or other things that can't be done in the constructor is so common. – Nir Friedman Aug 23 '17 at 17:56
-1

From your code, you need to allocate a dynamic 2D array. This is actually an array of pointers to arrays.

int _tmain(int argc, _TCHAR* argv[])
{
    int L = 10; // get from command line

    int ** s = new int*[L];
    for (int i = 0; i < L; i++)
        s[i] = new int[L];

    // DO SOMETHING

    // free memory
    for (int i = 0; i < L; i++)
        delete[] s[i];

    delete[] s;

    return 0;
};
EylM
  • 5,967
  • 2
  • 16
  • 28