Reputation:
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
Reputation: 30
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.
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
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
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