How do I declare a 2d array in C++ using new?

Viewed 1190211

How do i declare a 2d array using new?

Like, for a "normal" array I would:

int* ary = new int[Size]

but

int** ary = new int[sizeY][sizeX]

a) doesn't work/compile and b) doesn't accomplish what:

int ary[sizeY][sizeX] 

does.

29 Answers

If your row length is a compile time constant, C++11 allows

auto arr2d = new int [nrows][CONSTANT];

See this answer. Compilers like gcc that allow variable-length arrays as an extension to C++ can use new as shown here to get fully runtime-variable array dimension functionality like C99 allows, but portable ISO C++ is limited to only the first dimension being variable.

Another efficient option is to do the 2d indexing manually into a big 1d array, as another answer shows, allowing the same compiler optimizations as a real 2D array (e.g. proving or checking that arrays don't alias each other / overlap).


Otherwise, you can use an array of pointers to arrays to allow 2D syntax like contiguous 2D arrays, even though it's not an efficient single large allocation. You can initialize it using a loop, like this:

int** a = new int*[rowCount];
for(int i = 0; i < rowCount; ++i)
    a[i] = new int[colCount];

The above, for colCount= 5 and rowCount = 4, would produce the following:

enter image description here

Don't forget to delete each row separately with a loop, before deleting the array of pointers. Example in another answer.

int** ary = new int[sizeY][sizeX]

should be:

int **ary = new int*[sizeY];
for(int i = 0; i < sizeY; ++i) {
    ary[i] = new int[sizeX];
}

and then clean up would be:

for(int i = 0; i < sizeY; ++i) {
    delete [] ary[i];
}
delete [] ary;

EDIT: as Dietrich Epp pointed out in the comments this is not exactly a light weight solution. An alternative approach would be to use one large block of memory:

int *ary = new int[sizeX*sizeY];

// ary[i][j] is then rewritten as
ary[i*sizeY+j]

I presume from your static array example that you want a rectangular array, and not a jagged one. You can use the following:

int *ary = new int[sizeX * sizeY];

Then you can access elements as:

ary[y*sizeX + x]

Don't forget to use delete[] on ary.

This question was bugging me - it's a common enough problem that a good solution should already exist, something better than the vector of vectors or rolling your own array indexing.

When something ought to exist in C++ but doesn't, the first place to look is boost.org. There I found the Boost Multidimensional Array Library, multi_array. It even includes a multi_array_ref class that can be used to wrap your own one-dimensional array buffer.

typedef is your friend

After going back and looking at many of the other answers I found that a deeper explanation is in order, as many of the other answers either suffer from performance problems or force you to use unusual or burdensome syntax to declare the array, or access the array elements ( or all the above ).

First off, this answer assumes you know the dimensions of the array at compile time. If you do, then this is the best solution as it will both give the best performance and allows you to use standard array syntax to access the array elements.

The reason this gives the best performance is because it allocates all of the arrays as a contiguous block of memory meaning that you are likely to have less page misses and better spacial locality. Allocating in a loop may cause the individual arrays to end up scattered on multiple non-contiguous pages through the virtual memory space as the allocation loop could be interrupted ( possibly multiple times ) by other threads or processes, or simply due to the discretion of the allocator filling in small, empty memory blocks it happens to have available.

The other benefits are a simple declaration syntax and standard array access syntax.

In C++ using new:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (array5k_t)[5000];

array5k_t *array5k = new array5k_t[5000];

array5k[4999][4999] = 10;
printf("array5k[4999][4999] == %f\n", array5k[4999][4999]);

return 0;
}

Or C style using calloc:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (*array5k_t)[5000];

array5k_t array5k = calloc(5000, sizeof(double)*5000);

array5k[4999][4999] = 10;
printf("array5k[4999][4999] == %f\n", array5k[4999][4999]);

return 0;
}

The purpose of this answer is not to add anything new that the others don't already cover, but to extend @Kevin Loney's answer.

You could use the lightweight declaration:

int *ary = new int[SizeX*SizeY]

and access syntax will be:

ary[i*SizeY+j]     // ary[i][j]

but this is cumbersome for most, and can lead to confusion. So, you can define a macro as follows:

#define ary(i, j)   ary[(i)*SizeY + (j)]

Now you can access the array using the very similar syntax ary(i, j) // means ary[i][j]. This has the advantages of being simple and beautiful, and at the same time, using expressions in place of the indices is also simpler and less confusing.

To access, say, ary[2+5][3+8], you can write ary(2+5, 3+8) instead of the complex-looking ary[(2+5)*SizeY + (3+8)] i.e. it saves parentheses and helps readability.

Caveats:

  • Although the syntax is very similar, it is NOT the same.
  • In case you pass the array to other functions, SizeY has to be passed with the same name (or instead be declared as a global variable).

Or, if you need to use the array in multiple functions, then you could add SizeY also as another parameter in the macro definition like so:

#define ary(i, j, SizeY)  ary[(i)*(SizeY)+(j)]

You get the idea. Of course, this becomes too long to be useful, but it can still prevent the confusion of + and *.

This is not recommended definitely, and it will be condemned as bad practice by most experienced users, but I couldn't resist sharing it because of its elegance.

Edit:
If you want a portable solution that works for any number of arrays, you can use this syntax:

#define access(ar, i, j, SizeY) ar[(i)*(SizeY)+(j)]

and then you can pass on any array to the call, with any size using the access syntax:

access(ary, i, j, SizeY)      // ary[i][j]

P.S.: I've tested these, and the same syntax works (as both an lvalue and an rvalue) on g++14 and g++11 compilers.

Try doing this:

int **ary = new int* [sizeY];
for (int i = 0; i < sizeY; i++)
    ary[i] = new int[sizeX];

Below example may help,

int main(void)
{
    double **a2d = new double*[5]; 
    /* initializing Number of rows, in this case 5 rows) */
    for (int i = 0; i < 5; i++)
    {
        a2d[i] = new double[3]; /* initializing Number of columns, in this case 3 columns */
    }

    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            a2d[i][j] = 1; /* Assigning value 1 to all elements */
        }
    }

    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            cout << a2d[i][j] << endl;  /* Printing all elements to verify all elements have been correctly assigned or not */
        }
    }

    for (int i = 0; i < 5; i++)
        delete[] a2d[i];

    delete[] a2d;


    return 0;
}

If you want an 2d array of integers, which elements are allocated sequentially in memory, you must declare it like

int (*intPtr)[n] = new int[x][n]

where instead of x you can write any dimension, but n must be the same in two places. Example

int (*intPtr)[8] = new int[75][8];
intPtr[5][5] = 6;
cout<<intPtr[0][45]<<endl;

must print 6.

I don't know for sure if the following answer wasn't provided but I decided to add some local optimizations to the allocation of 2d array (e.g., a square matrix is done through only one allocation): int** mat = new int*[n]; mat[0] = new int [n * n];

However, deletion goes like this because of linearity of the allocation above: delete [] mat[0]; delete [] mat;

this is an old answer but I like to declarer dynamic arrays like this for C++

int sizeY,sizeX = 10;
 //declaring dynamic 2d array:
    int **ary = new int*[sizeY];
    for (int i = 0; i < sizeY; i++) 
    {
     ary[i] = new int[sizeX];
   }

you can change the size in run time like this. this is tested in c++ 98

I would suggest using 2D vectors over 2D arrays. Basically using vectors as much as possible mostly because

  1. dynamic memory allocation is hassle-free
  2. automatic memory management

here is a small code snippet where you can create a dynamic sized array

vector<vector<int>> arr;
for (int i=0; i<n; i++)
{    
    vector<int> temp;
    for (int j=0; j<k; j++)
    {
        int val;
        //assign values
        temp.push_back(val);
    }
    arr.push_back(temp);
}

if you want to declare a pre-defined pointer array:

int **x;
x = new int*[2] { 
        new int[2] { 0, 1 },
        new int[2] { 2, 3 } 
    };

access:

cout << x[0][0];

If you only use the array locally or inside a class, you can use lambda expression to create an array-like object.

int main(int argc, char **argv) {
  srand(time(0));
  int w = rand() % 20 + 10;
  int h = rand() % 20 + 10;
  {
    // Here. Only one line and no memory leak.
    auto arr = [=, p = std::make_unique<int[]>(w * h)](int i, int j) -> int & { return *&p[i * w + j]; };
    arr(1, 0) = 6;
    std::cout << arr(1, 0) << '\n';
  }
}

The object is not compatible with int[][], and to pass it as an argument, you will need templates. But it can release you from the trouble of getting [i * w + j] right when you access an element.

You can also use a bare std::unique_ptr<int[]> along with a getter implemented in lambda. But you may make mistakes and have dangling references.

int **arr = new int* [NoOfRows]
for(int i = 0; i<NoOfRows; i++)
   arr[i] = new int[noOfColumn];

This is the good way to declare the 2D array in c++ using new Here NoOfRow is showing that how many rows you want ans noOfColumn is showing how many column you want

Related