0

I have a problem with creating an array in constructor. Take a look at my code:

class foo
{
   private:
     const int size;
     double *tab;

   public:
     foo(int s);
};

foo::foo(int s):size(s)
{
   tab = new double[size][size];
}

Constructor can't create a new array because size of array is not a constant value... What's wrong with that? I bet it's really easy.

P.S. I apologize for my poor english.

SirPL
  • 51
  • 8
  • possible duplicate of [How do I declare a 2d array in C++ using new?](http://stackoverflow.com/questions/936687/how-do-i-declare-a-2d-array-in-c-using-new) – Brendan Long Apr 28 '14 at 17:18
  • Yes, that's duplicate. I tried to find similar question, but I didn't notice this one. – SirPL Apr 29 '14 at 15:46

5 Answers5

2

tab needs to be a double-pointer and you need to allocate the second dimension separately in a loop.

class foo
{
private:
    const int size;
    double **tab;

public:
    foo(int s);
    ~foo();
};

foo::foo(int s) : size(s)
{
    tab = new double*[size];
    for (int i = 0; i < size; ++i)
        tab[i] = new double[size];
}

foo::~foo()
{
    for (int i = 0; i < size; ++i)
        delete [] tab[i];
    delete [] tab;
}
ooga
  • 15,423
  • 2
  • 20
  • 21
1

Only the first dimension can be variable. Later ones must be compile-time constant.

tab = new double[size][10]; // For example.

In this case, tab needs to be a pointer to an array:

double (*tab)[10];

If you need the second dimension to also be variable, then you'll need to do something such as the other answers.

kec
  • 2,099
  • 11
  • 17
1

The problem is that in C++ array dimensions need to be known at compile, except possibly the first dimension, which you can supply to the array new[] operator at runtime.

There are several ways to fix your code:

  • Make tab a vector<vector<double> > and let C++ standard library worry about managing the memory,
  • Make tab a double**, allocate new double*[size], and then allocate the individual rows in a loop, or
  • Keep tab a double*, allocate new double[size*size], and do your own index translation when accessing the values.

I think the first approach is best, because it lets you avoid potential leaks without writing too much code:

class foo
{
   private:
     // const int size; <<== You don't need it - tab.size() gives you the size
     vector<vector<double>> tab;
   public:
     foo(int size);
};

foo::foo(int size)
:   tab( vector<vector<double> >(size, vector<double>(size, 0.0) ) )
{
}

If you do decide to go with the second or the third approach, remember to follow The Rule of Three.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

You need to allocate an array of array pointers first and then allocate each of the individual arrays. For a more thorough discussion see this article. Here is your code as I would recommend. Don't forget to include the destructor as I show here.

class foo
{
   private:
     const int size;
     double **tab;

   public:
     foo(int s);
     ~foo();
};

foo::foo(int s):size(s)
{
   tab = new double*[size];
   for (int i = 0; i < size; i++)
   {
       tab[i] = new double[size];
   }
}

foo::~foo()
{
    for (int i = 0; i < size; i++)
    {
        delete [] tab[i];
    }
    delete [] tab;
}
brader24
  • 485
  • 2
  • 10
0

Use a std::vector of std::vector of double:

typedef std::vector< double > double_vector;
typedef std::vector< double_vector > double_2d_vector;

[snip]

double_2d_vector tab;

[snip]

foo::foo(int s) 
    : size(s), tab( s, double_vector( s, 0.0 ) )
{
}

[snip]

tab[ x ][ y ] = 4.57;

You really shouldn't be using raw pointers.

Rob K
  • 8,757
  • 2
  • 32
  • 36
  • Although I agree with you why is tab declared as global but initialized within the foo constructor? That looks like a lazy example to me. – shawn1874 Apr 28 '14 at 17:36
  • That's not complete code. It's just snippets to show how things would be declared. – Rob K Apr 28 '14 at 17:38