Declare a multidimentional array without the size - c++

I want to declare an array of arrays or multidimensional array without knowing the size.
I want to do something similar to what I did in this cases with simple arrays:
int *array;
cin >> size;
array = new int[size];
Maybe I can loop to initialize a pointer of pointers like this:
int **array;
cin >> rows >> col;
array = new *int[rows]
for (int i = 0; i < rows; ++i)
array[i] = new int[col];
But I would prefer to not do this if a better solution exists.

Why not use std::vector?
std::vector<std::vector<int> > array;
If you don't want to use an array of pointers, you could use one large array that you allocate dynamically after you get the size and access it as an array of rows.
int rows = 10;
int columns = 20;
int* array = new int[rows * columns];
for (int count = 0; count < rows; count++)
{
int* row = &array[count * columns];
for (int inner_count = 0; inner_count < columns; inner_count++)
{
int* element = &row[inner_count];
//do something
}
}
delete [] array;

You're pretty much going to have to go with the loop version. You can make one slight improvement, which is to allocate one big block and then build your own int* index into it:
int **array;
int *storage;
cin >> rows >> col;
array = new *int[rows];
storage = new int[rows*col];
for (int i = 0; i < rows; ++i)
array[i] = storage + col * i;
This has the nice property that you can still use array[i][j] syntax for accessing the array.

You could use a single std::vector to contain the entire two dimensional array and wrap it in a class to hide the details. Here's an example, it uses a data( row, col ) member function that returns a reference to the element at row and col. I included an example 2 dimensional matrix of int where each entry in the array is initialized to the product of its row and col. When an instance of this class goes out of scope, the default destructor will get called and release the memory, that way you don't have to remember to call delete[] to release the memory. All elements of the matrix will be contiguous in memory, this is cache friendly and should give you good performance.
#include <iostream>
#include <vector>
#include <stdexcept>
template <typename T>
class matrix {
std::vector<T> data_;
public:
size_t const rows_;
size_t const cols_;
matrix(size_t rows, size_t cols)
: rows_(rows)
, cols_(cols)
, data_( rows * cols )
{}
T& data( size_t row, size_t col ) {
if (row > rows_ || col > cols_) throw std::out_of_range("matrix");
return data_[ row * cols_ + col ];
}
};
int main( int argc, char** argv )
{
matrix<int> array(100,100);
for(size_t r=0; r < array.rows_; ++r) {
for(size_t c=0; c < array.cols_; ++c) {
array.data(r,c) = r * c;
}
}
std::cout << "8 x 7 = " << array.data(8,7) << std::endl;
return 0; // array goes out of scope here, memory released automatically
}
When you run this you will get
8 x 7 = 56

If you care, you can have a little bit more convenience by have a helper
template <typename T>
struct C3DArray
{
vector<vector<vector<T>>> m;
C3DArray(int size_x, int size_y, int size_z)
: m(make(T(), size_z, size_y, size_x))
{ }
template <typename U> static std::vector<U> make(U v, size_t n) {
return { n, std::move(v) };
}
template <typename U, typename... Dim> static auto make(U v, size_t n, Dim... other)
-> std::vector<decltype(make(v, other...))> {
return { n, make(v, other...) };
}
};
This uses variadics. Use it like this:
C3DArray<int> arr(3,4,20);

Related

How to treat a pointer returned by malloc as a multidimensional array?

Is there a way to tell the compiler that I've allocated a memory of size N * M and I wanna treat this pointer as N * M array? In other words, is there a way to write something like this?:
int arr[N][M] = (int[N][M])malloc(N * M * sizeof(int));
arr[x][y] = 123;
I know that the compiler doesn't know the dimensions of the array, all it knows is that that's a pointer. so my question is: can I somehow tell the compiler that this pointer returned by malloc is an array pointer and it's dimensions are N * M? I can use an array to pointers, pointer to arrays or pointer to pointers, but in all cases I'll have to lookup 2 addresses. I want to have a contiguous memory on the heap and treat it as a multidimensional array. just like how I would write:
int arr[N][M];
Is there any way to achieve that?
In a C++ program you should use the operator new.
As for malloc then in C++ M shall be a constant expression if you want to allocate a two-dimensional array.
You can write for example
int ( *arr )[M] = ( int ( * )[M] )malloc( N * M * sizeof(int) );
or
int ( *arr )[M] = ( int ( * )[M] )malloc( sizeof( int[N][M] ) );
If to use the operator new then the allocation can look like
int ( *arr )[M] = new int[N][M];
If M is not a compile-time constant then you can use the standard container std::vector as it is shown in the demonstrative program below
#include <iostream>
#include <vector>
int main()
{
size_t n = 10, m = 10;
std::vector<std::vector<int>> v( n, { m } );
return 0;
}
What you want is a "matrix" class like
template <typename T>
class matrix
{
size_t len;
size_t width;
std::vector<T> data;
public:
matrix(size_t len, size_t width) : len(len), width(width), data(len*width) {}
T& operator()(size_t row, size_t col) { return data[width * row + col]; }
const T& operator()(size_t row, size_t col) const { return data[width * row + col]; }
size_t size() const { return len * width; }
};
int main(int argc, char const *argv[])
{
matrix<int> m(5, 7);
m(3, 3) = 42;
std::cout << m(3, 3);
}
This keeps all of the data in a single contiguous buffer, and doesn't have any undefined behavior unlike all the other examples that use malloc. It's also RAII, and you don't have to write any copy or move constructors since all of the members "do the right thing" with the compiler provided defaults. You can make this class more complicated, provide a proxy object so you can overload operator[] and be able to do m[][], but at it's base this is what you want.
If you what to avoid use of stack and you need large single block of data to keep two dimensional array of constant size (know at compile time) the this is the best cleanest way to do it:
std::vector<std::array<int, M>> arr(N);
arr[x][y] = 3;
Now if you need M is a value known at run-time, it would be best to use boost::multi_array
I do not see a reason to use malloc.
You can do exactly what you want with a helper function. This let's you specify the array size at runtime, and it uses malloc as requested (although typically you should be using new):
#include <iostream>
#include <string>
#include <memory>
template <class T>
T** Get2DMalloc(size_t m, size_t n) {
T** ret = (T**)malloc(sizeof(T*) * m);
for (size_t i = 0; i < m; ++i) {
ret[i] = (T*)malloc(sizeof(T) * n);
}
return ret;
}
template <class T>
void Free2D(T** arr, size_t m, size_t n) {
for (int i = 0; i < m; ++i) {
free(arr[i]);
}
free(arr);
}
int main() {
int m = 3;
int n = 3;
int** a = Get2DMalloc<int>(3, 3);
for (int x = 0; x < m; ++x) {
for (int y = 0; y < n; ++y) {
a[x][y] = x * m + y;
}
}
for (int i = 0; i < m * n; ++i) {
std::cout << a[i / m][i % n] << std::endl;
}
Free2D<int>(a, m, n);
system("pause");
return 0;
}

Initialise global array with respect to function input

I want to do something like:
int a[][]; // I know this code won't work, its to demonstrate what I want to do
void func(int n, int m){
a = int[n][m];
}
that is, initialise a global array whose size depends on function input. If this array was local, it would be a trivial case, but I don't know how to do this in the case shown above. Any help would be very useful!
You can create a matrix with std::vector:
std::vector<std::vector<int>> a;
void func(int n, int m) {
a.resize(n);
for(int i = 0; i < n; i++) {
a[i].resize(m);
}
}
Then you can access elements in the same way you do with int a[][]:
a[i][j] = number;
One way to achieve this is to encapsulate a flat std::vector in a Matrix class and use math to get an element with row and column as in this example:
template<typename T>
class Matrix {
private:
vector<T> vec;
//...
public:
T& get_value(size_t const row, size_t const col) {
return vec[row * col_count + col];
}
};
you can try this
int ** a; // is a pointer of two dimension
void func(int n, int m){
a = new int*[n]; //dynamic allocation global pointer a
for(int i = 0; i < n; i++)
a[i] = new int[m]();
}

How to create 2d array c++?

I need to create 2d array in c++.
I can't do it by int mas= new int[x][y]; or auto mas= new int[x][y];
I need to create an array dynamically like:
int x,y
auto mas= new int[x][y];//error - must be const.
Please help me.
int x,y;
x =3;
y = 5;
int ** mas = new int*[x];
for (int i=0;i<x;i++)
{
mas[i] = new int[y];
}
I think something like this.
Don't forget
for(int i=0;i<x;i++)
delete[] mas[i];
delete[] mas;
at the end.
The C++ tool for creating dynamically sized arrays is named std::vector. Vector is however one-dimensional, so to create a matrix a solution is to create a vector of vectors.
std::vector< std::vector<int> > mas(y, std::vector<int>(x));
It's not the most efficient solution because you pay for the ability to have each row of a different size. You you don't want to pay for this "feature" you have to write your own bidimensional matrix object. For example...
template<typename T>
struct Matrix
{
int rows, cols;
std::vector<T> data;
Matrix(int rows, int cols)
: rows(rows), cols(cols), data(rows*cols)
{ }
T& operator()(int row, int col)
{
return data[row*cols + col];
}
T operator()(int row, int col) const
{
return data[row*cols + col];
}
};
Then you can use it with
Matrix<int> mat(y, x);
for (int i=0; i<mat.rows; i++)
for (int j=0; j<mat.cols; j++)
mat(i, j) = (i == j) ? 1 : 0;
My advice would be to avoid the pain of multidimensional arrays in the first place and use a struct.
struct Point {
int x;
int y;
}
int points = 10;
Point myArray[points];
Then to access a value:
printf("x: %d, y: %d", myArray[2].x, myArray[2].y);
Depends on exactly what you're trying to achieve, though.
You can do the manipulations yourself.
int* mas = new int[x*y];
and access [i,j] by:
mas[i*y + j] = someInt;
otherInt = mas[i*y +j];
std::vector<std::vector<int> > mas(y, std::vector<int>(x));

How to allocate a 2D array of pointers in C++

I'm trying to make a pointer point to a 2D array of pointers. What is the syntax and how would I access elements?
By the letter of the law, here's how to do it:
// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
array2d[i] = new (int*)[cols];
}
// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
array2d[i][j] = NULL;
}
}
Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order.
However, more frequently in C++ you'd create a class that internally managed a 1D array of pointers and overload the function call operator to provide 2D indexing. That way you're really have a contiguous array of pointers, rather than an array of arrays of pointers.
It depends. It can be as simple as:
int main()
{
int* data[10][20]; // Fixed size known at compile time
data[2][3] = new int(4);
}
If you want dynamic sizes at runtime you need to do some work.
But Boost has you covered:
int main()
{
int x;
int y;
getWidthAndHeight(x,y);
// declare a 2D array of int*
boost::multi_array<int*,2> data(boost::extents[x][y]);
data[2][3] = new int(6);
}
If you are fine with jagged arrays that can grow dynamically:
int main()
{
std::vector<std::vector<int*> > data;
data.push_back(std::vector<int*>(10,NULL));
data[0][3] = new int(7);
}
Note: In all the above. I assume that the array does not own the pointer. Thus it has not been doing any management on the pointers it contains (though for brevity I have been using new int() in the examples). To do memory management correctly you need to do some more work.
int *pointerArray[X][Y];
int **ptrToPointerArray = pointerArray;
That's how you make a true (contiguous in memory) multidimensional array.
But realize that once you cast a multidimensional array to a pointer like that, you lose the ability to index it automatically. You would have to do the multidimensional part of the indexing manually:
int *pointerArray[8][6]; // declare array of pointers
int **ptrToPointerArray = &pointerArray[0][0]; // make a pointer to the array
int *foo = pointerArray[3][1]; // access one element in the array
int *bar = *(ptrToPointerArray + 3*8 + 1); // manually perform row-major indexing for 2d array
foo == bar; // true
int *baz = ptrToPointerArray[3][1]; // syntax error
double** array = new double*[rowCnt];
for (int row = 0; row < rowCnt; ++row)
array[row] = new double[colCnt];
for (int row = 0; row < rowCnt; ++row)
for (int col = 0; col < colCnt; ++col)
array[row][col] = 0;
You could try Boost::MultiArray.
Check out this page for details.
:)
I had these once in a piece of code I wrote.
I was the laughing stock of the team when the first bugs leaked out. On top of that we use Hungarian notation, leading to a name like papChannel - a pointer to an array of pointers...
It's not nice. It's nicer to use typedefs to define a 'row of columns' or vice versa. Makes indexing more clear, too.
typedef int Cell;
typedef Cell Row[30];
typedef Row Table[20];
Table * pTable = new Table;
for( Row* pRow = *pTable; pRow != *pTable+_countof(*pTable); ++pRow ) {
for( Cell* pCell = *pRow; pCell != *pRow + _countof(*pRow); ++pCell ) {
... do something with cells.
}
}
You can define a vector of vectors:
typedef my_type *my_pointer;
typedef vector<vector<my_pointer> > my_pointer2D;
Than create a class derived from my_pointer2D, like:
class PointersField: public my_pointer2D
{
PointsField(int n, int m)
{
// Resize vectors....
}
}
PointsField pf(10,10); // Will create a 10x10 matrix of my_pointer
I prefer to use the () operator. There are lots of reasons for this (C++ FAQs 13.10). Change the internal representation to a std::vector if you like:
template <class T, int WIDTH, int HIEGHT>
class Array2d
{
public:
const T& operator ()(size_t col, size_t row) const
{
// Assert col < WIDTH and row < HIEGHT
return m_data [( row * WIDTH + col)];
}
T& operator ()(size_t col, size_t row)
{
// Assert col < WIDTH and row < HIEGHT
return m_data [( row * WIDTH + col)];
}
private:
T m_data[WIDTH * HIEGHT];
};
You can use it like this:
Array2d< Object*, 10, 10 > myObjectArray;
myObjectArray(5,6) = new Object();
See my code. It works on my FC9 x86_64 system:
#include <stdio.h>
template<typename t>
struct array_2d {
struct array_1d {
t *array;
array_1d(void) { array = 0; }
~array_1d()
{
if (array) {
delete[] array;
array = 0;
}
}
t &operator[](size_t index) { return array[index]; }
} *array;
array_2d(void) { array = 0; }
array_2d(array_2d<t> *a) { array = a->array; a->array = 0; }
void init(size_t a, size_t b)
{
array = new array_1d[a];
for (size_t i = 0; i < a; i++) {
array[i].array = new t[b];
}
}
~array_2d()
{
if (array) {
delete[] array;
array = 0;
}
}
array_1d &operator[](size_t index) { return array[index]; }
};
int main(int argc, char **argv)
{
array_2d<int> arr = new array_2d<int>;
arr.init(16, 8);
arr[8][2] = 18;
printf("%d\n",
arr[8][2]
);
return 0;
}
Effo UPD: a response to "Isn't that an array of pointers to arrays?", adding the example of array of pointers, very simple:
int main(int argc, char **argv)
{
array_2d<int*> parr = new array_2d<int*>;
int i = 10;
parr.init(16, 8);
parr[10][5] = &i;
printf("%p %d\n",
parr[10][5],
parr[10][5][0]
);
return 0;
}
Did I still misunderstand your question?
And you could even
typedef array_2d<int*> cell_type;
typedef array_2d<cell_type*> array_type;
int main(int argc, char **argv)
{
array_type parr = new array_type;
parr.init(16, 8);
parr[10][5] = new cell_type;
cell_type *cell = parr[10][5];
cell->init(8, 16);
int i = 10;
(*cell)[2][2] = &i;
printf("%p %d\n",
(*cell)[2][2],
(*cell)[2][2][0]
);
delete cell;
return 0;
}
It also works on my FC9 x86_64 system.

Delaying array size in class definition in C++?

Is there some way to delay defining the size of an array until a class method or constructor?
What I'm thinking of might look something like this, which (of course) doesn't work:
class Test
{
private:
int _array[][];
public:
Test::Test(int width, int height);
};
Test::Test(int width, int height)
{
_array[width][height];
}
What Daniel is talking about is that you will need to allocate memory for your array dynamically when your Test (width, height) method is called.
You would declare your two dimensional like this (assuming array of integers):
int ** _array;
And then in your Test method you would need to first allocate the array of pointers, and then for each pointer allocate an array of integers:
_array = new *int [height];
for (int i = 0; i < height; i++)
{
_array [i] = new int[width];
}
And then when the object is released you will need to explicit delete the memory you allocated.
for (int i = 0; i < height; i++)
{
delete [] _array[i];
_array [i] = NULL;
}
delete [] _array;
_array = NULL;
vector is your best friend
class Test
{
private:
vector<vector<int> > _array;
public:
Test(int width, int height) :
_array(width,vector<int>(height,0))
{
}
};
I think it is time for you to look up the new/delete operators.
Seeing as this is a multidimensional array, you're going to have to loop through calling 'new' as you go (and again not to forget: delete).
Although I am sure many will suggest to use a one-dimensional array with width*height elements.
(Months later) one can use templates, like this:
// array2.c
// http://www.boost.org/doc/libs/1_39_0/libs/multi_array/doc/user.html
// is professional, this just shows the principle
#include <assert.h>
template<int M, int N>
class Array2 {
public:
int a[M][N]; // vla, var-len array, on the stack -- works in gcc, C99, but not all
int* operator[] ( int j )
{
assert( 0 <= j && j < M );
return a[j];
}
};
int main( int argc, char* argv[] )
{
Array2<10, 20> a;
for( int j = 0; j < 10; j ++ )
for( int k = 0; k < 20; k ++ )
a[j][k] = 0;
int* failassert = a[10];
}