How to dynamically allocate a 2D array in C++? - c++

How to create a 2d array using dynamic memory allocation in c++?
Maze(int c=10){
const int m=c;
a=new int[m][m];
}
void main(){
Maze(12);
}

std::vector is the typical way to have a dynamically allocated array in C++. You can have a vector of vectors to make it two-dimensional. Here's an example:
std::vector<std::vector<int>> a(m,std::vector<int>(m));
If you want it inside a class:
struct Maze {
std::vector<std::vector<int>> a;
Maze(int m) : a(m,std::vector<int>(m)) { }
};

Easily - using multiplication. Also I suggest using reference to array because in this way you specify the type more explicitly then using a pointer to it's first element. I'm actually amazed why this isn't the type most programmers use. Perhaps because they're lazy and the type is complex ;).
void Maze(int c=10) {
const int m=c;
int (&a)[0][0] = *(int (*)[0][0])new int[/*numbers of rows*/ m * sizeof(int) * m /* number of colums on each row*/];
}
Here 'a' is an reference to the newly created array. As types aren't dynamic in 'C++' language we assume that it has zero elements on each of it's dimensions. But of-course we can access more then 0.
Now if you have a function with parameter of type 2 dim array it will look like this:
void func(int (&_2dimarray)[0][0]) ;
Or if you want to return it from your 'Maze' you could write:
int (&Maze(int c=10))[0][0] {
const int m=c;
int (&a)[0][0] = *(int (*)[0][0])new int[/*numbers of rows*/ m * sizeof(int) * m /* number of colums on each row*/];
return a;
}
Life example.
But of-course the easiest way is using 'std::vector' which however can have performance cost on some compilers while the built-in array will more surely run fast everywhere.
EDIT: The explanation is simple - the 'new []' can be thought as a function like:
template<class T>
T *operator new T[] (std::size_t);
Your instance of it:
a=new int[m][m];
Can also look like this (illustrative)
a=operator new int[m][](m);
Which fulfills 'T' with 'int[m]'.
This is illegal because 'int[m]' is not valid type. 'C++' supports only static types and this is not such because the length of the array can't be determined during compile-time as 'm' is not a constant. The last 'm' is a function parameter to 'operator new[]'.
Yep I also think this construct isn't the most elegant yet but this is the life.

There are two approaches. If the size of the internal one-dimensional subarray is a constant value known at compile time then you can write
const size_t N = 10;
int ( * )[N] Maze( size_t n = N )
{
return new int[n][N];
}
int main()
{
int ( *a )[N] = Maze( 12 );
//...
delete [] a;
}
If it is not a constant then you need to allocate a one-dimensional array of pointers to one-dimensional arrays. For example
const size_t N = 10;
int ** Maze( size_t n = N )
{
int **p = new int *[n];
for ( size_t i = 0; i < n; i++ ) p[i] = new int[n];
return p;
}
int main()
{
int **a = Maze( 12 );
//...
for ( size_t i = 0; i < 12; i++ ) delete [] a[i];
delete [] a;
}
Also you could use smart pointers as for example std::unique_ptr.
The other approach is to use standard container std::vector<std::vector<int>>

Related

How to declare a dynamic 2D array in C++

I'm trying to define a dynamic 2D Array in C++ using the following definition:
int foo(string parameter){
const int n = parameter.length();
int* Array = new int[n][n];
return 0;
}
I receive an error that array size in new expression must be constant, can't understand why because Array is supposed to be dynamic.
(someone posted a shorter version of this in the comments while I was writing it).
What you need for a 2D array allocated with new is this:
int foo(string parameter){
const int n = parameter.length();
int* Array = new int[n*n];
return 0;
}
And then access cells with appropriate indexing.
Another solution is to use vector.
int foo(string parameter){
const int n = parameter.length();
vector<vector<int>> Array(n, vector<int>(n));
return 0;
}

Pointer casting with unknown array size in C++

how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time? Is it somehow possible? (I am doing this because, I pass an 2d array of unknow size to a func. So I cast 2d array to a void pointer and then in that func I want it to recast back.)
int i = 5;
int tab1[i][i];
//cast to void pointer
void *p = (void *)tab1;
//and recast back
int (*tab2)[5] = (int (*)[5])p; //this is working
int (*tab3)[i] = (int (*)[i])p; // but this is not
First I suggest to don't use runtime size for array in C/C++, except you using STL vector as an array. so instead of:
int i = 5;
you must use:
const int i = 5;
except you use Vector that is safe and better than intrinsic arrays.
how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time? Is it somehow possible?
If we talk about C intrinsic array, It is not possible!
why it is not possible?
because C/C++ compiler not aware of your the array size, borders,.... so if you cast your 2d array to 1d array, it is possible. it is the reason that tab2 array can access to first 5th element of your array. really C/C++ compiler cannot distinguish the different of
int a[3][3]
with
int a[3*3]
so You must be aware of at least one dimension of your array:
int main() {
const int i = 3,j = 4;
int tab1[i][j] = {1,2,3,4,5,6,7,8,9,10,11};
//cast to void pointer
void *p = (void *)tab1;
auto a = (int (*)[i][12/i])p;
return 0;
}
In the above example, I aware about i and total count(12) and I calculate the second dimension.
I use auto keyword that very easily inferred the data type.
int i = 5; int tab1[i][i]; is a VLA. It's not standard C++ and should be avoided.
An array-of-pointers-to-arrays (and vector-of-vectors) won't be as efficient as a true 2D array since it's no longer contiguous (int tab1[5][5] is a true 2D array and is stored contiguously in memory, but the dimensions must be known at compile-time).
You can easily create a custom 2D container class that would store the data in a contiguous 1D vector and apply some simple math (x + y*width) to access the elements.
Example:
class Matrix {
std::vector<int> data;
public:
const int width;
const int height;
Matrix(int width, int height) : width(width), height(height), data(width*height) {}
int operator()(int x, int y) const {
return data[y * width + x];
}
int& operator()(int x, int y) {
return data[y * width + x];
}
};
void print(Matrix const& mat) {
for (int y = 0; y < mat.height; y++) {
for (int x = 0; x < mat.width; x++)
std::cout << mat(x, y) << " ";
std::cout << std::endl;
}
}
int main() {
Matrix mat(5, 5);
mat(1, 1) = 1;
mat(2, 2) = 2;
mat(3, 3) = 3;
print(mat);
}
For convenience this overloads the () operator. It's still possible with the [] operator but that will require a proxy class to access the inner dimension(s) and also putting y before x since the dimensions are actually reversed.
int tab1[i][i]; is a non-standard compiler extension for variable length arrays. It is better to avoid this because it is not portable and hard to deal with as you are seeing. You would be better with:
std::vector<std::vector<int>> tab1(i, std::vector<int>(i));
Then your function can simply take this vector:
void foo(const std::vector<std::vector<int>>& array) { ....
how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time?
You can't. You can only cast to a type that is known at compile time.
What you can do is convert to a pointer to first element of the first row: int* p = static_cast<int*>(tab1);. You can then treat the array as one dimensional1. Converting two dimensional indices to one dimensional requires some trivial math: x, y -> x + y * i.
1 As long as you don't mind the technicality that pointer arithmetic across the sub array boundary might technically not be allowed by the standard. But that rule is silly. If you're concerned about this, then you should create a one dimensional array in the first place.
The problem you are having here is that the size of an array must be defined at compile time.
In your case, you have multiple options:
make i a constexpr like constexpr int i = 5;
use a int ** instead:
int i = 5;
int tab1[i][i];
//cast to void pointer
void *p = (void *)tab1;
// cast to int **
auto tab1_p = (int **)p;
// use it like it was an array
tab1_p[1][3] = 5;

How to dynamically allocate a contiguous 2D array in C++?

I need a 2d character array for use in a trash API that absolutely requires use of arrays and NOT vectors (much emphasis on this because all of my searching just had answers "use a vector". I wish I could).
I figured the way to do it would be to allocate an external array of size rows * character length, instead of doing:
char** arr;
arr = new char*[100];
// for loop that allocates the internal arrays
But I'm not sure what method I would need to use to make it contiguous? Do I need to allocate a massive 1D array first, then assign the 1D array to the 2D array in chunks?
As other answers have said: allocate n * m entries to create the contiguous data, and then it can be wrapped in pointers to create a 2d array.
... absolutely requires use of arrays and NOT vectors ...
I'm not sure if vector is a constraint based on the API being used, or requirements -- but it's worth noting that vector can be used for the memory management of the implementation -- while still using the raw data (which can be accessed by &vec[0] or vec.data(), which returns a pointer to the first element of the array, and can be used with functions accepting raw pointers).
Since this question is about c++, one option is to wrap an array of n * m in a class that acts like a 2-d array while actually being contiguous.
A simple example could be:
class array_2d
{
public:
array_2d( std::size_t rows, std::size_t columns )
: m_rows(rows), m_cols(columns), m_array( new char[rows * columns] )
{
}
~array_2d()
{
delete [] m_array;
}
// row-major vs column-major is up to your implementation
T& operator()( std::ptrdiff_t row, std::ptrdiff_t col )
{
// optional: do bounds checking, throw std::out_of_range first
return m_array[row * m_cols + col];
// alternatively:
// return m_array[col * m_rows + row];
}
// get pointer to the array (for raw calls)
char* data()
{
return m_array;
}
private:
char* m_array;
std::size_t m_rows;
std::size_t m_cols;
};
(Ideally char* would be std::unique_ptr<char[]> or std::vector<char> to avoid memory-leak conditions, but since you said vector is not viable, I'm writing this minimally)
This example overloads the call operator (operator()) -- but this could also be a named function like at(...); the choice would be up to you. The use of such type would then be:
auto array = array_2d(5,5); // create 5x5 array
auto& i01 = array(0,1); // access row 0, column 1
Optionally, if the [][] syntax is important to behave like a 2d-array (rather than the (r,c) syntax), you can return a proxy type from a call to an overloaded operator [] (untested):
class array_2d_proxy
{
public:
array_2d_proxy( char* p ) : m_entry(p){}
char& operator[]( std::ptrdiff_t col ){ return m_entry[col]; }
private:
char* m_entry;
};
class array_2d
{
...
array_2d_proxy operator[]( std::ptrdiff_t row )
{
return array_2d_proxy( m_array + (row * m_cols) );
}
...
};
This would allow you to have the 'normal' 2d-array syntax, while still being contiguous:
auto& i00 = array[0][0];
This is a good way to do it:
void array2d(int m, int n) {
std::vector<char> bytes(m * n);
std::vector<char*> arrays;
for (int i = 0; i != m * n; i += n) {
arrays.push_back(bytes.data() + i);
}
char** array2d = arrays.data();
// whatever
}
The main problem in C++ with "continuous 2d arrays with variable column length" is that an access like myArray[r][c] requires the compiler to know the column size of the type of myArray at compile time (unlike C, C++ does not support variable length arrays (VLAs)).
To overcome this, you could allocate a continuous block of characters, and additionally create an array of pointers, where each pointer points to the begin of a row. With such a "view", you can then address the continuous block of memory indirectly with a myArray[r][c]-notation:
int main() {
// variable nr of rows/columns:
int rows = 2;
int columns = 5;
// allocate continuous block of memory
char *contingousMemoryBlock = new char[rows*columns];
// for demonstration purpose, fill in some content
for (int i=0; i<rows*columns; i++) {
contingousMemoryBlock[i] = '0' + i;
}
// make an array of pointers as a 2d-"view" of the memory block:
char **arr2d= new char*[rows];
for (int r=0; r<rows;r++) {
arr2d[r] = contingousMemoryBlock + r*columns;
}
// access the continuous memory block as a 2d-array:
for (int r=0; r<rows; r++) {
for (int c=0; c<columns; c++) {
cout << arr2d[r][c];
}
cout << endl;
}
}

C/C++ allocation of arrays of array like objects

I am mostly a C programmer, and I am looking for a fast and elegant solution to do what I want in C++. Let us consider this simple data structure
struct mystruct
{
int * array1;
int * array2;
size_t size;
};
The two pointers array1 and array2 are to be thought as two arrays of length size. I need a huge amount of these (about 2**30 or 1.000.000.000) all of the same small size (about 100). All of them will be deallocated at the exact same time. I can do the following in C with only one call to malloc where K is the number of struct I need and N is the size of the arrays
EDITED VERSION (see the old one below)
size_t NN = N * sizeof(int);
struct mystruct * my_objects = malloc(K * sizeof(struct mystruct));
int * memory = malloc(2*K*NN);
for(i=0; i<K; ++i)
{
my_objects[i].size = N;
my_objects[i].array1 = memory + 2*i*NN;
my_objects[i].array2 = memory + (2*i+1)*NN;
}
...
free(my_objects);
free(memory);
This version does not support very huge K and does not allow me to resize the array. But it is not so hard to design something for that purpose. Is there a way of creating a class in C++ that would be a kind of std::vector<mystruct> with forbidden shrinking and for which the allocation of array1 and array2 would not be based on dynamical allocation for each entry? I do want to minimize the effect of memory allocation since K is very big.
OLD VERSION:
size_t KK = K * sizeof(mystruct);
size_t NN = N * sizeof(int);
struct mystruct * my_objects = (struct mystruct *) malloc(KK + 2*K*NN);
for(i=0; i<K; ++i)
{
my_objects[i].size = N;
my_objects[i].array1 = (int *) (my_objects + KK + 2*i*NN);
my_objects[i].array2 = (int *) (my_objects + KK + (2*i+1)*NN);
}
Here's my literal translation from C to C++ that maintains the same memory layout:
std::unique_ptr<int[]> const memory(new int[2 * K * N]);
std::vector<mystruct> my_objects;
my_objects.reserve(K);
for (int i = 0; i < K; ++i)
{
mystruct const tmp = {N, memory + 2*i*NN, memory + (2*i+1)*NN};
my_objects.push_back(tmp);
}
The following does two memory allocations, one for each vector. Naturally you have to ensure that the ints vector lives longer than mystructs vector, since mystructs's members refer to ints's members.
struct mystruct
{
int* array1;
int* array2;
std::size_t size;
};
std::vector<int> ints(N*2*K);
std::vector<mystruct> mystructs(K);
for (std::size_t i=0; i<K; i++) {
mystruct& ms = mystructs[i];
ms.array1 = &ints[2*N*i];
ms.array2 = &ints[2*N*i+1];
ms.size = N;
}
Update:
As tp1 pointed out, std::vector might reseat its internal array, invalidating all pointers into it. If you never add or remove elements, that is not an issue. If you do, consider using std::deque instead for ints. However then you also have more memory allocations upon construction, see What really is a deque in STL?. Note that sadly C++ does not allow a const std::vector of non-const elements, see Const vector of non-const objects.
Note: Solution created with minimal manual memory handling in mind, before OP edited in that his main requirement was performance due to a very large K. As std::vector still does behind-the-scenes memory allocations, this isn't a fast solution, just an elegant one.
Might be improved with a custom memory allocator, but I think #Simple's answer is better all-around, especially if encapsuled in a wrapper class.
struct MyStruct
{
std::vector< int > array1;
std::vector< int > array2;
std::size_t size;
MyStruct( std::size_t init_size ) :
array1( std::vector< int >( init_size ) ),
array2( std::vector< int >( init_size ) ),
size( init_size )
{}
};
// ...
std::vector< MyStruct > my_objects( K, N );
No dynamic memory allocation at all. (Well, not by you, anyway.)
What you are doing here in C is that allocating an array externally to your struct, and than pointing pointers to the different parts of this array.
You can do exactly the same thing with std::vector<> - have a huge vector defined outside of your struct, and point pointers to different parts of this vector. Same thing exactly.
If N and K are known at compile time, but can be different in different places, then a template will work:
template <int N, int K>
struct Memory {
Memory() {
for (int i=0; i < K; i++) {
mystruct[i].array1 = data1[i];
mystruct[i].array2 = data2[i];
size[i] = N;
}
}
struct mystruct {
int * array1;
int * array2;
size_t size;
} mystructs[K];
int data1[K][N];
int data2[K][N];
};
void f() {
// The constructor sets up all the pointers.
Memory *m<100,200> = new Memory<100,200>();
.....
}
(I've not checked if that compiles.)
If the values are not known then I would not attempt to do this in one allocation; it makes more sense to do two allocations, one for an array of mystruct, and one for the integers. The extra overhead is minimal, and the code is much more maintainable.
struct Memory {
Memory(int N, int K) {
mystructs = new mystruct[K];
data = new int[2*K*N];
for (int i=0; i < K; i++) {
array1[i] = &data1[2*i*N];
array2[i] = &data2[(2*i+1)*N];
size[i] = N;
}
}
struct mystruct {
int * array1;
int * array2;
size_t size;
} mystruct *mystructs;
int *data;
};
(Again, I've not checked that compiles.)
Note that where your code has 2*i*N*sizeof(int) you have a bug because C pointer arithmetic does not count bytes; it counts multiples of the pointer type. In my code I've made this explicit by taking the address of an array item, but the maths is the same.
What you're trying to do can be done using the exact same code in c++.
However, it is utterly inadvisable in c++. The reason c++ has Object-Oriented semantics is to avoid the very situation you're reckoning with. Here's how I would handle this:
struct mystruct {
vector<int> array1;
vector<int> array2;
mystruct(size_t size);
}
mystruct::mystruct(size_t size) {
array1.resize(size);
array2.resize(size);
}
int main() {
vector<mystruct> mystructarray(numOfStructs, numOfElementsOfArray1AndArray2);
//EDIT: You don't need to expressly call the mystruct constructor, it'll be implicitly called with the variable passed into the vector constructor.
//Do whatever
return 0;
}
vector objects can be queried for their size at runtime, so there's no need to store size as a field of mystruct. And since you can define constructors for structs, it's best to handle creation of the object in that way. Finally, with a valid constructor, you can initialize an array of mystruct with a vector, passing in a valid argument for mystruct's constructor to build the vector.
DOUBLE EDIT COMBO: Alright, let's try a different approach.
Based on what you indicated in your comments, it sounds like you need to allocate a LOT of memory. I'm thinking this data has specific meaning in your application, which means it doesn't make a lot of sense to use generic data structures for your data. So here's what I'm proposing:
class mydata {
private:
size_t num_of_sets;
size_t size_of_arrays;
std::vector<int> data;
public:
mydata(size_t _sets, size_t _arrays)
: data(_sets * _arrays * 2),
num_of_sets(_sets),
size_of_arrays(_arrays) {}
int * const array1(size_t);
int * const array2(size_t);
};
int * const mydata::array1(size_t index)
{
return &(data[index*size_of_arrays * 2]);
}
int * const mydata::array2(size_t index)
{
return &(data[index*size_of_arrays * 2 + size_of_arrays]);
}
int main(int argc, char** argv) {
mydata data(16'777'216, 10);
data.array1(5)[5] = 7;
data.array2(7)[2] = 8;
std::cout << "Value of index 5's array1 at index 5: " << data.array1(5)[5] << std::endl;
std::cout << "Value of index 7's array2 at index 2: " << data.array2(7)[2] << std::endl;
//Do Something
return 0;
}

How to create a pointer in C++ that points to a multidumentional array of int?

I know how to create a multidumentional array statndard way:
const int m = 12;
const int y = 3;
int sales[y][n];
And I know how to create a pointer that points to one dimentional array:
int * ms = new int[m];
But is it possible to create a pointer that points to multidumentional array?
int * sales = new int[y][m]; // doesn't work
int * mSales = new int[m]; // ok
int * ySales = new int[y]; // ok
mSales * ySales = new mSales[y]; // doesn't work, mSales is not a type
How to create such a pointer?
The expression new int[m][n] creates an array[m] of array[n] of int.
Since it's an array new, the return type is converted to a pointer to
the first element: pointer to array[n] of int. Which is what you have
to use:
int (*sales)[n] = new int[m][n];
Of course, you really shouldn't use array new at all. The
_best_solution here is to write a simple Matrix class, using
std::vector for the memory. Depending on your feelings on the matter,
you can either overload operator()( int i, int j ) and use (i, j)
for indexing, or you can overload operator[]( int i ) to return a
helper which defines operator[] to do the second indexation. (Hint:
operator[] is defined on int*; if you don't want to bother with
bounds checking, etc., int* will do the job as the proxy.)
Alternatively, something like:
std::vector<std::vector<int> > sales( m, n );
will do the job, but in the long term, the Matrix class will be worth
it.
Sure, it's possible.
You'll be creating a pointer to a pointer to an int, and the syntax is just like it sounds:
int** ptr = sales;
You've probably seen more examples of this than you think as when people pass arrays of strings (like you do in argv in main()), you always are passing an array of an array of characters.
Of course we'd all prefer using std::string when possible :)
I remember it was something like this:
int** array = new int*[m];
for(int i=0; i<m; i++) {
array[i] = new int[n];
}