user11360687
user11360687

Reputation:

Dynamically allocating memory

I am new to C++ and programming in general so i apologize if this is a trivial question.I am trying to initialize 2 arrays of size [600][600] and type str but my program keeps crashing.I think this is because these 2 arrays exceed the memory limits of the stack.Also,N is given by user so i am not quite sure if i can use new here because it is not a constant expression.

My code:

#include<iostream>

using namespace std;

struct str {
int x;
int y;
int z;
};
int main(){
cin>>N;
str  Array1[N][N]; //N can be up to 200
str  Array2[N][N];
};

How could i initialize them in heap?I know that for a 1-D array i can use a vector but i don't know if this can somehow be applied to a 2-D array.

Upvotes: 0

Views: 133

Answers (3)

Dien Tran
Dien Tran

Reputation: 30

How 2-or-more-dimensional arrays work in C++

A 1D array is simple to implement and dereference. Assuming the array name is arr, it only requires one dereference to get access to an element.

Arrays with 2 or more dimensions, whether dynamic or stack-based, require more steps to create and access. To draw an analogy between a matrix and this, if arr is a 2D array and you want access to a specific element, let's say arr[row][col], there are actually 2 dereferences in this step. The first one, arr[row], gives you access to the row-th row of col elements. The second and final one, arr[row][col] reaches the exact element that you need.

Because arr[row][col] requires 2 dereferences for one to gain access, arr is no longer a pointer, but a pointer to pointer. With regards to the above, the first dereference gives you a pointer to a specific row (a 1D array), while the second dereference gives the actual element.

Thus, dynamic 2D arrays require you to have a pointer to pointer.

To allocate a dynamic 2D array with size given at runtime

First, you need to create an array of pointers to pointers to your data type of choice. Since yours is string, one way of doing it is:

std::cin >> N;
std::string **matrix = new string*[N];

You have allocated an array of row pointers. The final step is to loop through all the elements and allocate the columns themselves:

for (int index = 0; index < N; ++index) {
    matrix[index] = new string[N];
}

Now you can dereference it just like you would a normal 2D grid:

// assuming you have stored data in the grid
for (int row = 0; row < N; ++row) {
    for (int col = 0; col < N; ++col) {
        std::cout << matrix[row][col] << std::endl;
    }
}

One thing to note: dynamic arrays are more computationally-expensive than their regular, stack-based counterparts. If possible, opt to use STL containers instead, like std::vector.

Edit: To free the matrix, you go "backwards":

// free all the columns
for (int col = 0; col < N; ++col) {
    delete [] matrix[col];
}

// free the list of rows
delete [] matrix;

Upvotes: 1

the boy
the boy

Reputation: 243

Normally, you can initialize memory in heap by using 'new' operator. Hope this can help you:

// Example program
#include <iostream>

struct str {
int x;
int y;
int z;
};

int main()
{
  int N;
  std::cin>>N;
  str  **Array1 = new str*[N]; //N can be up to 200
  for (int i = 0; i < N; ++i) {
    Array1[i] = new str[N];
  }
  // set value
  for (int row = 0; row < N; ++row) {
    for (int col = 0; col < N; ++col) {
        Array1[row][col].x=10;
        Array1[row][col].y=10;
        Array1[row][col].z=10;
    }
  }
  // get value
  for (int row = 0; row < N; ++row) {
    for (int col = 0; col < N; ++col) {
        std::cout << Array1[row][col].x << std::endl;
        std::cout << Array1[row][col].y << std::endl;
        std::cout << Array1[row][col].z << std::endl;
    }
  }
}

Upvotes: 0

David C. Rankin
David C. Rankin

Reputation: 84559

When wanting to allocate a 2D array in C++ using the new operator, you must declare a (*pointer-to-array)[N] and then allocate with new type [N][N];

For example, you can declare and allocate for your Array1 as follows:

#define N 200

struct str {
    int x, y, z;
};

int main (void) {

    str (*Array1)[N] = new str[N][N];  /* allocate */

    /* use Array1 as 2D array */

    delete [] Array1;                  /* free memory */
}

However, ideally, you would want to let the C++ containers library type vector handle the memory management for your. For instance you can:

#include<vector>
..
std::vector <std::vector <str>> Array1;

Then to fill Array1, fill a temporary std::vector<str> tmp; for each row (1D array) of str and then Array1.push_back(tmp); to add the filled tmp vector to your Array1. Your access can still be 2D indexing (e.g. Array1[a][b].x, Array1[a][b].y, ..., but you benefit from auto-memory management provided by the container. Much more robust and less error prone than handling the memory yourself.

Upvotes: 0

Related Questions