I am making a polynomial program, and below is the code I have written for it.
class Polynomial{
private:
int n; //n = degree of polynomial
double a[n]; //a = array of coefficients where a[i] is the coefficient of x^i
double roots[n];
double maxima[n-1],minima[n-1],inflection[n-1]; //arrays of coordinates of maxima, minima and points of inflection
This is just a part of the class Polynomial in the header file. When I try compiling, it gives me the following error
invalid use of non-static data member int n;
and when I make n static , it gives me the following error
array bound is not an integer constant before ‘]’ token
This is on compiling the header file alone. What am I doing wrong?
Your class contains VLA (variable lenghth arrays) which is not
supported in C++.
You need to either determine the size by making n constant
or use another type of container that is dynamic, std::vector
is a container that resembles an array but is dynamic i.e. can
be expanded during runtime.
class Polynomial
{
static const int n = 10;
double a[n];
...
class Polynomial
{
std::vector<double> a;
The size of C-style arrays must be known at compile time.
If n is in fact known at compile-time, you could make it a template parameter instead of a member variable.
If not then you will have to use a different container, such as vector<double> a, roots, maxima, minima, inflection; .
You can simply allocate all these in a constructor using new.
Or use vectors.
class Polynomial
{
vector<double> a;
Polynomial()
{
a.assign(n,0);
...
}
..
};
Without getting into complications,
the simple answer is that for static memory allocation to work (which is what you are trying to do with double a[n];) you need to know the size of the array at compile time.
However, if you do not know the size of the array even before the program runs, but instead, expect to know it somewhere during the runtime of the program, then you need to use dynamic memory allocation.
To do this you will have to
Declare pointers instead of static arrays.
and
Assign them memory using the new directive
and then later
When you don't need them, for instance when the scope of the class ends, you will have to free the memory you allocated using the delete directive with [] parenthesis to indicate the compiler to free memory for more than one consecutive variable.
Do something like:
class Polynomial{
private:
int n; //n = degree of polynomial
double *a; //a = array of coefficients where a[i] is the coefficient of x^i
double *roots;
double *maxima,*minima,*inflection; //arrays of coordinates of maxima, minima and points of inflection
public:
Polynomial( int degree_of_polynomial ){
n = degree_of_polynomial;
a = new double[n];
roots = new double[n];
maxima = new double[n-1];
minima = new double[n-1];
inflection = new double[n-1];
~Polynomial(){
delete []a;
delete []roots;
delete []maxima;
delete []minima;
delete []inflection;
}
}
For a more detailed explanation of dynamic memory allocation see this link.
Related
Am I breaking C++ coding conventions writing a helper function which allocates a 2D array outside main()? Because my application calls for many N-dimensional arrays I want to ensure the same process is followed. A prototype which demonstrates what I am doing :
#include <iostream>
// my helper function which allocates the memory for a 2D int array, then returns its pointer.
// the final version will be templated so I can return arrays of any primitive type.
int** make2DArray(int dim1, int dim2)
{
int** out = new int* [dim1];
for (int i = 0; i < dim2; i++) { out[i] = new int[dim2];}
return out;
}
//helper function to deallocate the 2D array.
void destroy2DArray(int** name, int dim1, int dim2)
{
for (int i = 0; i < dim2; i++) { delete[] name[i]; }
delete[] name;
return;
}
int main()
{
int** test = make2DArray(2,2); //makes a 2x2 array and stores its pointer in test.
//set the values to show setting works
test[0][0] = 5;
test[0][1] = 2;
test[1][0] = 1;
test[1][1] = -5;
// print the array values to show accessing works
printf("array test is test[0][0] = %d, test[0][1] = %d, test[1][0] = %d, test[1][1] = %d",
test[0][0],test[0][1],test[1][0],test[1][1]);
//deallocate the memory held by test
destroy2DArray(test,2,2);
return 0;
}
My concern is this may not be memory-safe, since it appears I am allocating memory outside of the function in which it is used (potential out-of-scope error). I can read and write to the array when I am making a single small array, but am worried when I scale this up and there are many operations going on the code might access and alter these values.
I may be able to sidestep these issues by making an array class which includes these functions as members, but I am curious about this as an edge case of C++ style and scoping.
There is a difference between allocating 2D arrays like this and what you get when you declare a local variable like int ary[10][10] that based on your statement
My concern is that this operation may not be memory-safe, since it
appears that I am allocating memory for an array outside of the
function in which it is used (potential out-of-scope error)
I am guessing you do not fully understand.
You are allocating arrays on the heap. Declaring a local variable like int ary[10][10] places it on the stack. It is the latter case where you need to worry about not referencing that memory outside of its scope-based lifetime; that is, it is the following that is totally wrong:
//DON'T DO THIS.
template<size_t M, size_t N>
int* make2DArray( ) {
int ary[M][N];
return reinterpret_cast<int*>(ary);
}
int main()
{
auto foo = make2DArray<10, 10>();
}
because ary is local to the function and when the stack frame created by the call to make2DArray<10,10> goes away the pointer the function returns will be dangling.
Heap allocation is a different story. It outlives the scope in which it was created. It lasts until it is deleted.
But anyway, as others have said in comments, your code looks like C not C++. Prefer an std::vector<std::vector<int>> rather than rolling your own.
If you must use an array and are allergic to std::vector, create the 2d array (matrix) as one contiguous area in memory:
int * matrix = new int [dim1 * dim2];
If you want to set the values to zero:
std::fill(matrix, (matrix + (dim1 * dim2)), 0);
If you want to access a value at <row, column>:
int value = matrix[(row * column) + column];
Since the matrix was one allocation, you only need one delete:
delete [] matrix;
I need to init/use a double ** (decleared in my header):
double **pSamples;
allocating (during the time) a matrix of NxM, where N and M are get from two function:
const unsigned int N = myObect.GetN();
const unsigned int M = myObect.GetM();
For what I learnt from heap and dynamic allocation, I need keyword new, or use STL vector, which will manage automatically allocate/free within the heap.
So I tried with this code:
vector<double> samplesContainer(M);
*pSamples[N] = { samplesContainer.data() };
but it still says I need a constant value? How would you allocate/manage (during the time) this matrix?
The old fashioned way of initializing a pointer to a pointer, is correctly enough with the new operator, you would first initialize the the first array which is a pointer to doubles (double*), then you would iterate through that allocating the next pointer to doubles (double*).
double** pSamples = new double*[N];
for (int i = 0; i < N; ++i) {
pSambles[i] = new double[M];
}
The first new allocates an array of double pointers, each pointer is then assigned to the array of pointers allocated by the second new.
That is the old way of doing it, remember to release the memory again at some point using the delete [] operator. However C++ provide a lot better management of sequential memory, such as a vector which you can use as either a vector of vectors, or simply a single vector capable of holding the entire buffer.
If you go the vector of vector way, then you have a declaration like this:
vector<vector<double>> samples;
And you will be able to reference the elements using the .at function as such: samples.at(2).at(0) or using the array operator: samples[2][0].
Alternatively you could create a single vector with enough storage to hold the multidimensional array by simply sizing it to be N * M elements large. However this method is difficult to resize, and honestly you could have done that with new as well: new double[N * M], however this would give you a double* and not a double**.
Use RAII for resource management:
std::vector<std::vector<double>> samplesContainer(M, std::vector<double>(N));
then for compatibility
std::vector<double*> ptrs(M);
for (std::size_t i = 0; i != M; ++i) {
ptrs[i] = samplesContainer[i].data();
}
And so pass ptrs.data() for double**.
samplesContainer.data() returns double*, bur expression *pSamples[N] is of type double, not double*. I think you wanted pSamples[N].
pSamples[N] = samplesContainer.data();
I have created a dynamic matrix of class objects but i have made a big mess with handling the returned pointers.
My intention is to create a matrix of class Point( Int x,Int y) and later to use it in different ways in the program.
Everything is working but i can't figure out the returned pointers game between the functions.
class Point
{
private:
int x;
int y;
public:
Point(int x,int y);
void SetPoint(int x,int y);
};
In a second class I use a Point object as class member.
Init_Pallet() is used to Initialize the Matrix.
class Warehouse
{
private:
Robot r1,r2;
Point *Pallet_Matrix;
public:
Point* Init_Pallet();
};
This is the Init function
Point* Warehouse::Init_Pallet()
{
int rows =10,cols =10;
Point** Pallet_Matrix = new Point*[rows];
for (int i = 0; i < rows; i++)
Pallet_Matrix[i] = new Point[cols];
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; j++) //Pallet matrix Init, x point for robots amount in position and y for box amount
Pallet_Matrix[i][j].SetPoint(0,0);
return *Pallet_Matrix;
}
The Init function is called by WareHouse C'Tor (ignore the other vars)
Warehouse::Warehouse(Robot p_r1,Robot p_r2): r1(p_r1),r2(p_r2)
{
this->r1=p_r1;
this->r2=p_r2;
Point *p =Init_Pallet();
this->Pallet_Matrix=p;
}
My question is: How do I return the address to the beginning of the matrix from the Init function to the C'Tor who called it?
And second question: how do i access the matrix different locations in the format of Matrix[i][j] after returning the matrix adress to the C'Tor.
Thank you in advance for all the help and your time.
You should just have Init_Pallet return a Point** and then do return Pallet_Matrix;. Currently you're copying one of the Point*s that you allocated out of the function, so the copy is no longer part of a contiguous array that you can index.
Don't forget to delete[] the dynamically arrays in your destructor.
However, you should much prefer to use the standard library containers like std::array or std::vector. Then you don't need to worry about the dynamic allocation yourself and no pointers to get in a mess with.
If I were doing it, I would just have:
class Warehouse
{
public:
Warehouse() : Pallet_Matrix() { }
private:
Robot r1,r2;
std::array<std::array<Point, 10>, 10> Pallet_Matrix;
};
And that's it. No init needed. No dynamic allocation. No assigning 0 to every element (if you give Point a default constructor that zero-initialises). Done.
How do I return the address to the beginning of the matrix from the Init function to the C'Tor?
In case you would really need just an address of first element, pretty straightforward would be:
return &Pallet_Matrix[0][0];
how do i access the matrix different locations in the format of Matrix[i][j] after returning the matrix address
Init_Pallet is a member function, which could simply work with the Pallet_Matrix member directly. Otherwise, the Init_Pallet function could actually return Point**, which should however make you feel that something's wrong with this code.
Better[1] solution would be:
Define the default constructor for Point:
class Point
{
public:
Point() : x(0), y(0){}
...
Use std::vectors instead of dynamically allocated arrays:
class Warehouse
{
private:
std::vector< std::vector<Point> > Pallet_Matrix;
and instead of:
Point *p =Init_Pallet();
this->Pallet_Matrix=p;
you would simply use std::vector's constructor:
int rows = 10, cols = 10;
Pallet_Matrix = std::vector< std::vector<Point> >(rows, cols);
[1] Better = You don't want to handle the memory management on your own.
The problem is that the returned type of Init_Pallet() is wrong — its a row, not a matrix. And in the last line of Warehouse::Init_Pallet() you dereference the proper pointer to matrix obtaining the pointer to the first row of the matrix.
You need to write Point **Pallet_Matrix; in Warehouse, use Point** Warehouse::Init_Pallet() definition of Init_pallet(), and return Pallet_Matrix in the last line of Init_Pallet().
The notation Point *row means the row is "the array of points" or "the pointer to the beginning of the array of points". The notation Point **matrix means the matrix is "the array of pointers to the beginnings of the arrays of points" or "the pointer to the beginning of such an array".
First: are the dimensions really constant, or is this just an
artifact of your having simplified the code for posting? If
they are really constant, there's no need for dynamic
allocation: you can just write:
Point palletMatrix[10][10];
and be done with it. (If you have C++11, it's even better; you
can use std::array, and palletMatrix will have full object
semantics.)
If you do need dynamic indexes, the only reasonable way of
doing this is to write a simple matrix class, and use it:
class Matrix
{
int m_rows;
int m_columns;
std::vector<Point> m_data;
public:
Matrix( int rows, int columns )
: m_rows( rows )
, m_columns( columns )
, m_data( rows * columns, Point( 0, 0 ) )
{
}
Point& operator()( int i, int j )
{
return m_data[ i * m_columns + j ];
}
// ...
};
Trying to maintain a table of pointers to tables is not a good
solution: it's overly complex, it requires special handling to
ensure that each row has the same number of columns, and it
generally has poor performance (on modern machines, at least,
where locality is important and multiplication is cheap).
Note too that the actual data is in an std::vector. There are
practically no cases where a new[] is a good solution; if you
didn't have std::vector (and there was such a time), you'd
start by implementing it, or something similar. (And
std::vector does not use new[] either.)
EDIT:
One other thing: if you're putting Point in a matrix, you might
want to give it a default constructor; this often makes the code
simpler.
I've got a class and I'm going to declare the size of the array (two dimensional) based on input from a user.
so :
class myClass {/*...*/}
int main(){
myClass* arrayObj = new myClass[100][100];
That works fine, and it should put the array on the heap.
But I need to do :
int arraySize;
cin >> arraySize;
myClass* arrayObj = new myClass[arraySize][arraySize];
I am getting the error :
"arraySize" cannot appear in a constant-expression.
I'm assuming that means that I can only have constants in the declaration of the array, but if not, then how can I do it?
The array is too big to fit on the stack, that is why I am doing it on the heap in the first place.
Edit : I've got it working with the pointers, but I'm having another problem, I have a function that is using the array, ie.
void myFunction()
{
/*...*/
arrayObj[something][something].variable = somethingElse // error here
}
int main ()
{
/*...*/
int arraySize;
cin >> arraySize;
MyClass **arrayObj = new MyClass*[arraySize]
for (int i = 0; i < arraySize; i++) arrayObj[i] = new MyClass[arraySize]
/*...*/
}
I'm getting : error: 'arrayObj' was not declared in this scope.
I can see why, but it's on the heap and it's a pointer, shouldn't it be global? If not, how would I make it global?
First of all you are mistaken saying that this
class myClass {/*...*/}
int main(){
myClass* arrayObj = new myClass[100][100];
works fine. The compiler shall issue an error because there is no implicit conversion from myClass ( * )[100] to myClass *
As for your problem then you should use the following approach:
myClass **arrayObj = new myClass *[arraySize];
for ( int = 0; i < arraySize; i++ ) arrayObj[i] = new myClass[arraySize];
C++ doesn't really have a built-in model of variable sized multi-dimensional arrays. Only the outermost dimension can vary at run-time, all other dimensions are fixed. The background is how C++ does address arithmetic: when adding an offset to a pointer it is advanced by the size of an object with a statically determined size.
If you want to have a multi-dimensional array varying in other dimensions, you'll need to use a suitable class or implement one yourself (the standard C++ library has std::valarray<T> to sort of deal with multi-dimensional arrays but their use is, let say, not entirely straight forward). The easiest approach is probably to use a std::vector<std::vector<myClass> >.
A more efficient approach is to allocate a large std::vector<myClass> as a member of a class and have operator[]() for this class return a view to a corresponding section of this array. For starters I would probably just use a std::vector<std::vector<myClass> > wrapped into a class and change the implementation if it turns out to be too inefficient.
If you must use arrays, then another way to get around this is impose a limit on the number of elements in the array and make sure that this limit is enforced in your code. This is one of the disadvantages of using arrays vs. std::vectors. Arrays are a fixed size while vectors can keep growing dynamically. By the way, what do you mean by "The array is too big to fit on the stack, that is why I am doing it on the heap in the first place."? If it is too big to fit on the stack, then maybe we should look at why the array is so large in the first place. Maybe there is a better way to solve whatever problem you're trying to deal with.
Hey everyone. I am an experienced java programmer and am just learning C++.
Now I have a bit of a beginner's problem. I have an array variable x of type int.
The user will input the size of x in method B. I want to use x in method A.
void method A()
{
using int x [] blah blah blah
}
void method B()
{
int n;
cin >>n;
int x [n]; // How can I use this int x in method A without getting error: storage size x is unknown.
// Or the error 'x' was not declared in this scope.
}
EDIT: Parameter passing isn't a solution I am looking for.
DOUBLE EDIT: I do know about the vector option, but my program is cramming on time. I am creating an algorithm where every millisecond counts.
BTW I found out a way of doing it.
int x [] = {}
method B();
method A () { blah blah use x}
method B () {/*int*/ x [n]}
If you actually want an array and not a vector, and you want that array dynamically sized at runtime, you would need to create it on the heap (storing it in a pointer), and free it when you're done.
Coming from Java you need to understand that there's no garbage collection in C++ - anything you new (create on the heap) in an object you will want to clean up in the destructor with delete.
class foo
{
private:
int *array;
public:
foo() { array = NULL; };
~foo()
{
if (array != NULL)
delete [] array;
}
void createArray()
{
array = new int[5];
}
};
More info at: http://www.cplusplus.com/doc/tutorial/dynamic/
This is a version of your example that works in c++.
#include <iostream>
int *my_array;
void methodA(a,b){
my_array[a] = b;
}
int methodB(){
int n;
std::cin >> n;
my_array = new int[n];
}
int main(){
int x;
x = methodB();
methodA(x-1, 20);
delete [] my_array;
return 0;
}
Use a vector:
std::vector<int> x(n);
then pass that to method A as an argument of type std::vector<int> const &.
Edit: Or make the vector a data member of your class and set it with:
size_t n;
std::cin >> n;
x.resize(n);
In C++ you can't directly size an array with a runtime value, only with constants.
You almost certainly want vector instead:
std::vector<int> x(n);
EDIT: flesh out answer.
I can't quite tell if you are trying to learn about arrays, or if you are trying to solve some practical problem. I'll assume the latter.
The only way for method A to have access to any variable is if it is in scope. Specifically, x must either be:
a local, including a parameter (but you said no to parameter passing)
a class member, or
a global
Here is a solution in which x is a class member:
class C {
public:
std::vector<int> x;
void A() {
std::cout << x[2] << "\n"; // using x[], for example.
}
void B() {
int n;
cin >> n;
x = std::vector<int>(n); // or, as others have pointed out, x.resize(n)
}
};
Be aware that arrays in C++ are much more basic (and dangerous) than in Java.
In Java, every access to an array is checked, to make sure the element number you use is within the array.
In C++, an array is just a pointer to an allocated area of memory, and you can use any array index you like (whether within the bounds of the array, or not). If your array index is outside the bounds of the array, you will be accessing (and modifying, if you are assigning to the array element!) whatever happens to be in memory at that point. This may cause an exception (if the memory address is outside the area accessible to your process), or can cause almost anything to happen (alter another variable in your program, alter something in the operating system, format your hard disk, whatever - it is called "undefined behaviour").
When you declare a local, static or global array in C++, the compiler needs to know at that point the size of the array, so it can allocate the memory (and free it for you when it goes out of scope). So the array size must be a constant.
However, an array is just a pointer. So, if you want an array whose size you don't know at compile time, you can make one on the heap, using "new". However, you then take on the responsibility of freeing that memory (with "delete") once you have finished with it.
I would agree with the posters above to use a vector if you can, as that gives you the kind of protection from accessing stuff outside the bounds of the array that you are used to.
But if you want the fastest possible code, use an allocated array:
class C {
int [] x;
void method A(int size)
{
x = new int[size]; // Allocate the array
for(int i = 0; i < size; i++)
x[i] = i; // Initialise the elements (otherwise they contain random data)
B();
delete [] x; // Don't forget to delete it when you have finished
// Note strange syntax - deleting an array needs the []
}
void method B()
{
int n;
cin >> n;
cout << x[n];
// Be warned, if the user inputs a number < 0 or >= size,
// you will get undefined behaviour!
}
}