Domanda

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.

È stato utile?

Soluzione

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;
}

Altri suggerimenti

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.

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.

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;
}

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top