Trigger1
Trigger1

Reputation: 3

C++ std::bad alloc error in initialising class objects

I'm trying to build the following class

class Matrix
{unsigned int RowNumber, ColumnNumber;
 double** Coefficients = new double*[RowNumber];

public:

 Matrix() : RowNumber(1), ColumnNumber(2)
 {/* Rownumber=1; 
     ColumnNumber=2; */
  for(int i=0; i<RowNumber;i++)
   {Coefficients[i]=FillRow(ColumnNumber);}}
};

All works fine, but when i try to initialise RowNumber and ColumnNumber inside the scope of constructor Matrix(), by removing the comment, instead of using the initialising list, i get an error "terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc". Why?

P.S. The problem is not in the function FillRow because i've used it in other parts of the code and it works fine, but for completness i report it here:

double* FillRow(unsigned int ColumnNumber)
{double*RowCoefficients = new double[ColumnNumber-1];
 static unsigned int CounterFillRow=1;
 double k;
 cout << "Insert " << ColumnNumber << " coefficients for the " << CounterFillRow << "th row\n";
 for(int i=0; i!=ColumnNumber; i++)
 {cin >> k;
  RowCoefficients[i]=k;}
 CounterFillRow++;
 return RowCoefficients;}

Upvotes: 0

Views: 86

Answers (2)

Alex
Alex

Reputation: 1031

That is because double** Coefficients = new double*[RowNumber]; occurs in initialization phase, before constructor body execution. If you move RowNumber to the constructor body, here new double*[RowNumber] RowNumber is undefined, which leads to exception

Upvotes: 1

Artyer
Artyer

Reputation: 40891

The problem is in your default value. If you omit a member initialiser, it's default constructed. For the case of unsigned int RowNumber, it will be a garbage value. (In practise, it will be a arbitrary number)

You have a default value for double** Coefficients, new double*[RowNumber];. If you don't initialise RowNumber, when you do new double*[RowNumber]; and RowNumber happens to be really high, it can't allocate enough memory, so it throws a std::bad_alloc.

With the member initialiser it's like this:

unsigned int RowNumber(1);
unsigned int ColumnNumber(2);
double** Coefficients = new double*[RowNumber];  // new double*[2];

for(int i=0; i<RowNumber;i++)
 {Coefficients[i]=FillRow(ColumnNumber);}}

Without, it looks like this:

unsigned int RowNumber;  // Garbage value
unsigned int ColumnNumber;
double** Coefficients = new double*[RowNumber];  // Reading garbage value

RowNumber = 1;
ColumnNumber = 2;

for(int i=0; i<RowNumber;i++)
 {Coefficients[i]=FillRow(ColumnNumber);}}

To fix this, either don't set a default for Coefficients or set the default to nullptr, and do new double*[RowNumber] in the body of the constructor.

Upvotes: 1

Related Questions