Transfering a dynamically allocated matrix in a method of a class in C++ - c++

I'm trying to make a dynamically allocated bidimensional array with variable size but I don't know why if I create my own constant value it won't compile:
const int oConstanta=N+1;
int (*m)[oConstanta]=new int[oConstanta][oConstanta];
But when I use a normal constant such as 1000 between the brackets it compiles successfully.
const int oConstanta=N+1;
int (*m)[1000]=new int[1000][1000];
Does anyone know the reason for this?
PS: I know that:
int **m=new int*[oConstanta];
for(i=1;i<=N;i++)
{
m[i]=new int[oConstanta];
init(m[i]);
}
will solve my problems but I want to learn why my former method was a bad idea.

Unless N is a compile-time constant expression, oConstanta is not a compile-time constant either.
The best way of making a two-dimensional array in C++ is using std::vector of std::vectors, for example, like this:
#include <vector>
std::vector<std::vector<int> > m(N+1, std::vector<int>(N+1, 0));

Ultimately the reason is that you can't create static arrays of variable length.
In your code you are trying to create a static array of dynamic arrays, both of variable length.
Now, static arrays live in the stack, while dynamic arrays live in the heap. While the memory management of the heap is "flexible", the stack is different: the compiler needs to be able to determine the size of each frame in the stack. This is clearly not possible if you use an array of variable length.
On the other hand, if you use a pointer the size of the stack frame is known (a pointer has a known size) and everything is fine.
If you want to try, this should compile fine
int (*m)[1000]=new int[oConstanta][1000]
since it's a fixed-size static array, whose entries are dynamically allocated arrays of variable length (allowed).
In short: whenever the size of an object is not known at compile time, that object cannot be in the stack, it has to be dynamically allocated.

To make a dynamically sized, 2D matrix with contiguous elements and a single allocation:
std::vector<int> matrix(Rows*Columns);
Access an element in the i th row and j th column:
matrix[Columns*i + j] = 1;
You can wrap this all up in a class. Here's a very basic example:
struct Matrix {
std::vector<int> m;
size_t rows,columns;
Matrix(size_t rows,size_t columns)
: rows(rows)
, columns(columns)
, m(rows*columns)
{}
int &at(size_t i,size_t j) {
return m.at(i*columns + j);
}
};

Related

C++: How to create a member 2D-array of size determined at runtime

I've tried to declare an empty pointer to a pointer, assign to it pointer to allocated during construction memory and iterate over it doing the assignment again, but I'm missing something. Also I wonder if it's possible to do this with the std::array. Attaching the code:
// Cell.h
class Cell {
char contents;
bool is_free;
};
// Memory.h
#include "Cell.h"
#include <cstddef>
class Memory {
public:
Memory(std::size_t nlines, std::size_t ncols);
private:
Cell **cells;
};
// Memory.cpp
#include "Memory.h"
Memory::Memory(std::size_t nlines, std::size_t ncols):
cells(new Cell[nlines]) // Cannot initialize a member subobject of type 'Cell **' with an rvalue of type 'Cell *'
{
for (std::size_t i = 0; i < nlines; ++i)
cells[i] = new Cell[ncols];
}
In addition I need my array to contain Cells with values char contents = '.', bool is_free = true after it is initialized. Which is the best way to do it?
UPD: I've thought of creating a 2D pseudo-array using a single pointer (not a pointer to a pointer) and accessing a cell with i*ncols + j.
Also I'm curious if it's possible to do this with the std::array
You can not, the size of an std::array is specified as a template parameter and your array is dynamically sized.
Rather than dealing with raw pointers, you should look at std::vector for dynamically sized arrays:
std::vector<std::vector<Cell>> cells{ncols, std::vector{nlines, Cell{}}};
The key benefit is that you avoid having to manually allocate and manage memory.
UPD: I've thought of creating a 2D pseudo-array using a single pointer (not a pointer to a pointer) and accessing a cell with i*ncols + j.
This is a much better idea, keeping your data in a single flat vector reduces fragmentation.
std::vector<Cell> cells(nlines*ncols, Cell{});
To make access easier, you can wrap this 1D vector in a class which exposes a operator()(std::size_t row, std::size_t col), that does the conversion from (row, col) indices to the location in the 1d array.
You need to write
Memory::Memory(std::size_t nlines, std::size_t ncols)
:cells(new *Cell[nlines])
{
...
}
(Note the Cell * instead of Cell).
std::array is compile-time fixed array size only, so it is not suitable for your purpose.
I would agree to your edit. Do not an array of pointers for matrices, use the flat array approach with indexing i*ncols + j. This former is more difficult to work with and has higher overhead (due to many new calls).
If you are worried about the multiplications overhead, you could make a look-up table for i*ncols. But I doubt that it is worth it.

CodeForces Q. 71A, Why isn't this compiling? [duplicate]

#include <iostream>
#include <fstream>
#include <cmath>
#include <math.h>
#include <iomanip>
using std::ifstream;
using namespace std;
int main (void)
{
int count=0;
float sum=0;
float maximum=-1000000;
float sumOfX;
float sumOfY;
int size;
int negativeY=0;
int positiveX=0;
int negativeX=0;
ifstream points; //the points to be imported from file
//points.open( "data.dat");
//points>>size;
//cout<<size<<endl;
size=100;
float x[size][2];
while (count<size) {
points>>(x[count][0]);
//cout<<"x= "<<(x[count][0])<<" ";//read in x value
points>>(x[count][1]);
//cout<<"y= "<<(x[count][1])<<endl;//read in y value
count++;
}
This program is giving me expected constant expression error on the line where I declare float x[size][2]. Why?
float x[size][2];
That doesn't work because declared arrays can't have runtime sizes. Try a vector:
std::vector< std::array<float, 2> > x(size);
Or use new
// identity<float[2]>::type *px = new float[size][2];
float (*px)[2] = new float[size][2];
// ... use and then delete
delete[] px;
If you don't have C++11 available, you can use boost::array instead of std::array.
If you don't have boost available, make your own array type you can stick into vector
template<typename T, size_t N>
struct array {
T data[N];
T &operator[](ptrdiff_t i) { return data[i]; }
T const &operator[](ptrdiff_t i) const { return data[i]; }
};
For easing the syntax of new, you can use an identity template which effectively is an in-place typedef (also available in boost)
template<typename T>
struct identity {
typedef T type;
};
If you want, you can also use a vector of std::pair<float, float>
std::vector< std::pair<float, float> > x(size);
// syntax: x[i].first, x[i].second
The array will be allocated at compile time, and since size is not a constant, the compiler cannot accurately determine its value.
You cannot have variable length arrays (as they are called in C99) in C++. You need to use dynamically allocated arrays (if the size varies) or a static integral constant expression for size.
The line float x[size][2] won't work, because arrays have to be allocated at compile time (with a few compiler-specific exceptions). If you want to be able to easily change the size of the array x at compile time, you can do this:
#define SIZE 100
float x[SIZE][2];
If you really want to allocate the array based on information you only have at runtime, you need to allocate the array dynamically with malloc or new.
The size of an automatic array must be a compile-time constant.
const int size = 100;
float x[size][2];
If the size weren't known at compile-time (e.g entered by the user, determined from the contents of the file), you'd need to use dynamic allocation, for example:
std::vector<std::pair<float, float> > x(somesize);
(Instead of a pair, a dedicated Point struct/class would make perfect sense.)
Because it expected a constant expression!
Array dimensions in C (ignoring C99's VLAs) and C++ must be quantities known at compile-time. That doesn't mean just labelled with const: they have to be hard-coded into the program.
Use dynamic allocation or std::vector (which is a wrapper around dynamic array allocation) to determine array sizes at run-time.
It is a restriction of the language. Array sizes must be constant expressions. Here's a partial jsutification from cplusplus.com
NOTE: The elements field within brackets [] which represents the number of elements the array is going to hold, must be a constant value, since arrays are blocks of non-dynamic memory whose size must be determined before execution. In order to create arrays with a variable length dynamic memory is needed, which is explained later in these tutorials.
You haven't assigned any value to size; thus the compiler cannot allocate the memory for the array. (An array of null size? What?)
Additionally, you'd need to make SIZE a constant, and not a variable.
EDIT: Unfortunately, this response no longer makes sense since the poster has changed their question.

declare and initialize 2d array with unknown size

I take the size of rows n and columns m from the user
I want to make a 2D array (matrix) of the size nxm , initialize it and do some work on it
int main()
{
int m,n;
cin>>m>>n;
const int grow=m;
const int gcol=n;
auto G = new double[grow][gcol](); //GIVES ERROR that grow and gcol must be const
/*int** G = new int*[n];
for (int i = 0; i < n; ++i)
G[i] = new int[n];*/
}
You can always index in a one dimensional array with y * gcol + x to make it effectively work as a two dimensional one. With that you can use a dynamic memory e.g. with a std::vector<double>.
//GIVES ERROR that grow and gcol must be const
No, it does not. Unless your compiler is bad. Read the error again.
It gives an error that gcol must be a constant expression.
You cannot have dynamic arrays of dynamic arrays. It's simply not possible in c++. You can only have dynamic arrays of things that have a static size, known at compile time.
Therefore, you cannot have a 2D array where both dimensions are determined at runtime.
You have 2 alternatives:
Use a dynamic array of pointers to dynamic arrays. Which is what you have there, commented out. A dynamic array of vectors works too.
Use a flat, one dimensional array that contains the rows in succession.
In either case, I recommend using a class to manage the memory. std::vector, perhaps.
Array size is part of the type and needs to be known at compile time. You get it at runtime. Use vectors instead.

Should I use vectors instead of arrays?

If I have a fixed number of elements of class MyClass, should I use arrays or vectors?, ie:
MyClass* myArray[];
or
std::vector<MyClass*> myVector;
?
Use std::array or raw arrays for a small, static number of elements.
If you have a lot of elements (more than say 100kb), you hog the stack and are asking for stack corruption / overflow. In that case, or if the number of elements can only be known at runtime, use std::vector.
if you know the number in compile time - use static array.
if the number is dynamic (obtained from the user) - vector is much better to save you the hurdle of managing the memory
"Fixed" has two meanings in this context. The usual one is set once, never change, such as a value read from input. This value is known at runtime and requires dynamic allocation on the heap. Your options are a C-style array with new or a vector; it is highly recommended you use a vector.
#include <vector>
#include <iostream>
int main() {
int size;
std::cin >> size;
int *myArray = new int[size];
std::vector<int> myVector(size);
}
"Fixed" can also mean a compile-time constant, meaning it is constant for any run of the program. You can use a C-style array or a C++ array (automatic memory allocation on the stack).
#include <array>
int main() {
const int size = 50;
int myArray[size];
std::array<int, size> myArray;
}
These are faster, but your program needs to have access to sufficient stack memory, which is something you can change in your project settings. See this topic for more info. If the size of the array is really big, you may want to consider allocating on the Heap anyway (vector).

C++ expected constant expression

#include <iostream>
#include <fstream>
#include <cmath>
#include <math.h>
#include <iomanip>
using std::ifstream;
using namespace std;
int main (void)
{
int count=0;
float sum=0;
float maximum=-1000000;
float sumOfX;
float sumOfY;
int size;
int negativeY=0;
int positiveX=0;
int negativeX=0;
ifstream points; //the points to be imported from file
//points.open( "data.dat");
//points>>size;
//cout<<size<<endl;
size=100;
float x[size][2];
while (count<size) {
points>>(x[count][0]);
//cout<<"x= "<<(x[count][0])<<" ";//read in x value
points>>(x[count][1]);
//cout<<"y= "<<(x[count][1])<<endl;//read in y value
count++;
}
This program is giving me expected constant expression error on the line where I declare float x[size][2]. Why?
float x[size][2];
That doesn't work because declared arrays can't have runtime sizes. Try a vector:
std::vector< std::array<float, 2> > x(size);
Or use new
// identity<float[2]>::type *px = new float[size][2];
float (*px)[2] = new float[size][2];
// ... use and then delete
delete[] px;
If you don't have C++11 available, you can use boost::array instead of std::array.
If you don't have boost available, make your own array type you can stick into vector
template<typename T, size_t N>
struct array {
T data[N];
T &operator[](ptrdiff_t i) { return data[i]; }
T const &operator[](ptrdiff_t i) const { return data[i]; }
};
For easing the syntax of new, you can use an identity template which effectively is an in-place typedef (also available in boost)
template<typename T>
struct identity {
typedef T type;
};
If you want, you can also use a vector of std::pair<float, float>
std::vector< std::pair<float, float> > x(size);
// syntax: x[i].first, x[i].second
The array will be allocated at compile time, and since size is not a constant, the compiler cannot accurately determine its value.
You cannot have variable length arrays (as they are called in C99) in C++. You need to use dynamically allocated arrays (if the size varies) or a static integral constant expression for size.
The line float x[size][2] won't work, because arrays have to be allocated at compile time (with a few compiler-specific exceptions). If you want to be able to easily change the size of the array x at compile time, you can do this:
#define SIZE 100
float x[SIZE][2];
If you really want to allocate the array based on information you only have at runtime, you need to allocate the array dynamically with malloc or new.
The size of an automatic array must be a compile-time constant.
const int size = 100;
float x[size][2];
If the size weren't known at compile-time (e.g entered by the user, determined from the contents of the file), you'd need to use dynamic allocation, for example:
std::vector<std::pair<float, float> > x(somesize);
(Instead of a pair, a dedicated Point struct/class would make perfect sense.)
Because it expected a constant expression!
Array dimensions in C (ignoring C99's VLAs) and C++ must be quantities known at compile-time. That doesn't mean just labelled with const: they have to be hard-coded into the program.
Use dynamic allocation or std::vector (which is a wrapper around dynamic array allocation) to determine array sizes at run-time.
It is a restriction of the language. Array sizes must be constant expressions. Here's a partial jsutification from cplusplus.com
NOTE: The elements field within brackets [] which represents the number of elements the array is going to hold, must be a constant value, since arrays are blocks of non-dynamic memory whose size must be determined before execution. In order to create arrays with a variable length dynamic memory is needed, which is explained later in these tutorials.
You haven't assigned any value to size; thus the compiler cannot allocate the memory for the array. (An array of null size? What?)
Additionally, you'd need to make SIZE a constant, and not a variable.
EDIT: Unfortunately, this response no longer makes sense since the poster has changed their question.