How do i allocate memory for a 2d array?

23,178

Solution 1

It seems you need pointer to pointer. EDIT: Well, to be more exact, the following example creates an array of pointers to arrays.

First do:

int **p = new int*[NUM];

Here you've created array of pointers. Now you need to create another array for every of them. That you can do this way:

for(int i = 0; i < NUM; i++)
{
    p[i] = new int[ANOTHER_NUM];
}

For deallocation you do similar, but in reverse way:

for(int i = 0; i < NUM; i++)
{
    delete[] p[i];
}

And finally:

delete[] p;

Now you can work with it. This way you can create N-dimensional array, just add more '*'. If you have any other particular question, ask in the comments, please.

But, generally, for further info I recommend you to try Google first with questions like "2D array in C++" or "dynamic allocation of 2D array C++", i. e. this query.

Solution 2

Other answers cover having a pointer array for your rows, with a pointer to an int array per row. Another option is to simply allocate a 1-D array big enough to hold all the 2-D array's elements:

int* p = new int [3 * 4];

Then instead of using the p[r][c] syntax, you use p[r * kNumCols + c]. In this example, kNumCols = 4. This is generally what's done in LAPACK-style number crunching, since it keeps things contiguous in memory and you don't need to allocate so many memory blocks.

Note: This generally is not slower than the alternative in practice, because the row offset calculation is moved out of the loop by the common subexpression optimization. Also, many optimizers know to look for this pattern. Further, by keeping your data co-located in a single block of memory, the data is more likely to stay in cache.

In C++, you could implement the p[][] notation with a helper template class:

template<class T>
class Array2DPtrRow
{public:
    Row(T* row_): row(row_) {}
    operator T*() { return row; }
    T& operator [](size_t c) { return row[c]; }
private:
    T* row;
};

template<class T, size_t NC>
class Array2DPtr
{public:
    Array2DPtr(T* buf_): buf(buf_) {}
    operator T*() { return buf; }
    Array2DPtrRow<T> operator [](size_t r)
        { return Array2DPtrRow<T>(buf + NC * r); }
private:
    T* buf;
};

This optimizes down to the same code as above, but allows you to use [][] notation and requires you to know your array dimensions at compile time. Usage example:

Array2DPtr<int, 4> p(new int[3 * 4]);
p[1][2];

This could be converted to make NC into a class member instead of a template parameter, but then the final object isn't just a pointer any more:

template<class T>
class Array2DPtr
{public:
    Array2DPtr(T* buf_, size_t nc_): buf(buf_), nc(nc_) {}
    operator T*() { return buf; }
    Array2DPtrRow<T> operator [](size_t r)
        { return Array2DPtrRow<T>(buf + nc * r); }
private:
    T* buf;
    size_t nc;
};

Array2DPtr<int> p(new int[3 * 4], 4);
p[1][2];

Note that none of these classes need copy constructors, assignment operators, or destructors because they don't take ownership of the pointed-to memory any more than a regular pointer does. So to release the memory, you still need to do:

delete[] p;

Or if your compiler can't figure it out:

delete[] (int*)p;

Solution 3

To actually answer the question:

Remember that an array is equivalent to a pointer to the first element of the array, so for instance you can write:

char str[14] = "Hello, world!";
char *ptr = str;

This works for a two-dimensional array as well.

int (*p)[4];

declares a pointer to the first element of a two-dimensional array. p can then be pointed at any two-dimensional array, as long as its second dimension is 4, so for instance you could write

int arr[3][4];
int (*p)[4] = arr;

Of course you can also allocate the memory dynamically:

int (*p)[4] = new int[3][4];

Again, the second dimension has to be 4, but you can vary the first dimension.

Solution 4

There are several ways to declare multidimensional arrays in C.

You can declare p explicitly as a 2D array:

int p[3][4];  // All of p resides on the stack.

(Note that new isn't required here for basic types unless you're using C++ and want to allocate them on the heap.)

Or you can declare it as a vector (1D array) of pointers, and then allocate memory for each vector:

int *p[3];                         // The vector addresses reside on the stack.
for (int i=0; i<3; i++) {
  p[i] = malloc(4 * sizeof(int));  // Each element resides on the heap.
}

// You can now access p as p[j][k] as if it were a 2D array.

for (int i=0; i<3; i++) {
  free p[i];
}

Or, if you don't know either dimension, you can allocate the entire 2D array dynamically:

#define WIDTH 3
#define HEIGHT 4
int **p;                              // Base address resides on the stack.

p = malloc(WIDTH * sizeof(int *));    // Pointers to vectors reside on the heap.
for (int i=0; i<WIDTH; i++) {
  p[i] = malloc(HEIGHT * sizeof(int)); // Data values reside on the heap.
}

// You can now access p as p[j][k] as if it were a 2D array.

// Release the memory that was allocated to each vector.
for (int i=0; i<WIDTH; i++) {
  free(p[i]);
}
// Release the memory that was allocated to the initial pointer.
free(p);

Solution 5

You need something like this

int **array_ptr; //two * are needed because it is a pointer to a pointer

array_ptr=new int*[firstnumber]; //creates a new array of pointers to int objects

for(int i=0; i<firstnumber; ++i)
array_ptr[i]=new int[secondnumber];
Share:
23,178
Nirvan
Author by

Nirvan

Updated on April 09, 2020

Comments

  • Nirvan
    Nirvan about 4 years

    How do i declare a 2d array using the 'new' operator? My book says this:

    int (*p)[4];
    p=new[3][4];
    

    but it doesn't make sense to me. p is a pointer to an array of 4 ints, so how can it be made to point to a 2d array?

    • dexametason
      dexametason about 12 years
    • thecoshman
      thecoshman about 12 years
      Why are none of these answers accepted? You have answers that explain simply how to correct your mistake, what exactly is wrong with what you are doing, how to best write what you are attempting and how to best achieving the end result of a 2D array, explaining the pros and cons of using a dynamically allocated array vs something like std::vector. Why have you not at least commented on answers that are not telling you what you want to know, perhaps the author of the answer could provide the missing information for you
    • james
      james about 12 years
      @thecoshman he might not have privilege to accept answer.
    • Nirvan
      Nirvan about 12 years
      @thecoshman well i got my answer
    • irsis
      irsis over 10 years
  • Adam Liss
    Adam Liss about 12 years
    Worth noting that this is the most memory-efficient implementation because there's no overhead for the vector of pointers. However, the code may be longer and/or slower if you need to calculate the index each time you reference an element. Often a good compromise is to allocate the array as a single vector like this, and then access it with a pointer.
  • thecoshman
    thecoshman about 12 years
    For all who care, there was a long thread on here trying to find out what the OP was actually after. Sadly, before the OP could explain him self and get the help he is after the meta police came along and swept it all aside. The long and short of it was, this (apparently) is not what the OP is after
  • Mike DeSimone
    Mike DeSimone about 12 years
    Guess I need to brush up on my telepathy.
  • Mohammad Jafar Mashhadi
    Mohammad Jafar Mashhadi over 11 years
    if we use this method to create an array, how should we free the memory with delete? this code doesn't work: for (int i = 0 ; i < firstnumber ; i++ ) delete array_ptr[i]; delete [] array_ptr;
  • v01d
    v01d over 11 years
    the code is working for me. the result of valgrind shows that all the memory is freed. Just delete[] array_ptr has to be out of the for cycle.