Variable sized arrays in C++ classes?
Question
Wednesday, July 9, 2014 12:56 PM
The following code compiles in code::blocks (using the gcc compiler) but not in VS-C++. So I conclude that, variable sized arrays in classes are not allowed in VS-C++. Am I right or is there a way to get around this issue?
btw, gcc compiles but warns me like:
"warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default]"
...
int MaxDim;
class CMatrix
{
public:
int n = MaxDim;
int nSqr = n * n;
double *a = new double [nSqr];
double *b = new double [n];
CMatrix (string s)
{
...
}
~CMatrix ()
{
...
}
};
...
void main ()
{
...
FileInput >> MaxDim;
...
CMatrix* a;
a = new CMatrix ("Matrix.txt");
...
delete (a);
}
All replies (9)
Wednesday, July 9, 2014 3:13 PM ✅Answered | 1 vote
I conclude that, variable sized arrays in classes are not allowed in VS-C++.
That's an exaggeration. You can do the allocations in the constructor:
#include "stdafx.h"
#include <string>
using namespace std;
int MaxDim;
class CMatrix
{
public:
// int n = MaxDim;
// int nSqr = n * n;
int n; // ***
int nSqr; // ***
// double *a = new double [nSqr];
// double *b = new double [n];
double *a; // ***
double *b; // ***
CMatrix (string s)
{
n = MaxDim; // ***
nSqr = n * n; // ***
a = new double [nSqr]; // ***
b = new double [n]; // ***
// ...
}
~CMatrix ()
{
delete[] a; // ***
delete[] b; // ***
// ...
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CMatrix cm("testit");
return 0;
}
Note that relying on the existence of a global variable such as MaxDim in this example and
your posted code is definitely a bad idea. Better to pass it as an argument to the constructor.
- Wayne
Wednesday, July 9, 2014 3:27 PM ✅Answered | 1 vote
Note that relying on the existence of a global variable such as MaxDim in this example and
your posted code is definitely a bad idea. Better to pass it as an argument to the constructor.
As in this example:
class CMatrix
{
public:
int n;
int nSqr;
double *a;
double *b;
CMatrix (string s, int MaxDim) : n(MaxDim) // ***
{
nSqr = n * n;
a = new double [nSqr];
b = new double [n];
// ...
}
int _tmain(int argc, _TCHAR* argv[])
{
int MaxDim = 10;
CMatrix cm("testit", MaxDim);
return 0;
}
- Wayne
Wednesday, July 9, 2014 9:44 PM ✅Answered
This is what I did and it's working perfect! Thanks again WayneAKing. You made my day.
edit: "delete (a);" converted to "delete [] a;" as Wayne suggested.
#include <iostream>
#include <fstream>
#include <string>
class CMatrix
{
public:
int n;
double *a, *u, *i, *b, *x;
CMatrix (string FileName, int MatrixDim)
{
n = MatrixDim;
a = new double [n * n];
u = new double [n * n];
i = new double [n * n];
b = new double [n];
x = new double [n];
...
...
...
}
~CMatrix ()
{
MatrixFreeMem ();
}
void MatrixFreeMem ()
{
delete [] a;
delete [] u;
delete [] i;
delete [] b;
delete [] x;
}
...
...
...
};
...
...
...
void main ()
{
...
...
...
CMatrix *A;
A = new CMatrix (gAppPath + gDataFileName, MaxDim); // max dim read previously from another file
A -> MatrixSolve ();
delete A;
}
Wednesday, July 9, 2014 10:11 PM ✅Answered | 1 vote
CMatrix (string FileName, int MatrixDim) { n = MatrixDim; a = new double [n * n]; u = new double [n * n]; i = new double [n * n]; b = new double [n]; x = new double [n]; ... ... ... } ~CMatrix () { MatrixFreeMem (); } void MatrixFreeMem () { delete (a); delete (u); delete (i); delete (b); delete (x); }
Your delete statements are of the wrong form. They should be:
delete[] a;
delete[] u;
delete[] i;
delete[] b;
delete[] x;
Use delete[] when you use new[] and use delete when you use new.
This is critical when the objects are classes, as using new[] calls the constructors for
each object in the array and delete[] calls the destructors for each object in the array.
Using delete instead of delete[] will cause the dtors to be skipped (with the possible
exception of the first one) - and the actual behaviour will be "undefined".
Note that parentheses are not needed:
char *c = new char[10];
...
delete[] c;
MyClass *mc = new MyClass;
...
delete MyClass;
- Wayne
Wednesday, July 9, 2014 2:45 PM | 1 vote
The following code compiles in code::blocks (using the gcc compiler) but not in VS-C++. So I conclude that, variable sized arrays in classes are not allowed in VS-C++.
gcc compiles but warns me like:
"warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default]"
It would help of you stated which *version* of VC++/VS you're using. According to this table:
Support For C++11 Features (Modern C++)
http://msdn.microsoft.com/en-us/library/hh567368.aspx
"Non-static data member initializers" is an available feature in VS/VC++ 2013 but not in
earlier versions.
- Wayne
Wednesday, July 9, 2014 3:42 PM
On 09/07/2014 14:56, merkez3110 wrote:
The following code compiles in code::blocks (using the gcc compiler) but not in VS-C++. So I conclude that, variable sized arrays in classes are not allowed in VS-C++. Am I right or is there a way to get around this issue?
btw, gcc compiles but warns me like:
"warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default]"
The problem is not variable sized arrays in classes, the problem is non-static data member initializer feature, that is a C++11 feature that might not be implemented in the Visual C++ compiler that you are using.
WayneAKing already posted a link to a table with C++11 features implemented in Visual C++, and also offered an alternative solution if non-static data member initializer feature is not available.
I'd just like to add that using RAII-based STL containers like std::vector is much better than using those raw C like array, which tend to produce code that can leak memory, is exception unsafe, and is also more complex.
Consider just using std::vector<double> instead of your raw C-like heap allocated double arrays.
Giovanni
Wednesday, July 9, 2014 5:21 PM
Thanks for the reply. I'm using VS-2012 and now I see that why I can't compile.
Wednesday, July 9, 2014 10:34 PM
I will take into account: convert "delete (a)" to "delete [] a".
Friday, July 11, 2014 5:42 PM
On 10/07/2014 00:11, WayneAKing wrote:
CMatrix (string FileName, int MatrixDim) { n = MatrixDim; a = new double [n * n]; u = new double [n * n]; i = new double [n * n]; b = new double [n]; x = new double [n]; ... ... ... } ~CMatrix () { MatrixFreeMem (); } void MatrixFreeMem () { delete (a); delete (u); delete (i); delete (b); delete (x); }
Your delete statements are of the wrong form. They should be:
delete[] a; delete[] u; delete[] i; delete[] b; delete[] x;
Use delete[] when you use new[] and use delete when you use new.
Just use std::vector, and you don't have to remember to delete/delete[] anything. In modern C++ code, convenient RAII building blocks like std::vector should be used, instead of those old C style raw new/new[] and delete/delete[] (unless there is a particular need to do that). Giovanni