A few days ago I learned about creating 2D allocated memory arrays from the internet, it works perfect. To access the array we just simply use matrix[i][j], however is there any way that I can dereference this 2D array by using * notation instead of [] for input as well as other methods?
First questions is solved I can use *(*(matrix + i) + j)
Now I got another question, last code segment is to free the allocated memory (I got it from internet as well), but I don't understand it, why cant I just use delete [] matrix ?
int **matrix;
// dynamically allocate an array
matrix = new int *[row];
for (int count = 0; count < row; count++)
{
matrix[count] = new int[col];
}
// input element for matrix
cout << endl << "Now enter the element for the matrix...";
for (int i=0; i < row; i++)
{
for (int j=0; j < col; j++)
{
cout << endl << "Row " << (i+1) << " Col " << (j+1) << " :";
cin >> matrix[i][j]; // is there any equivalent declaration here?
}
}
// free dynamically allocated memory
for( int i = 0 ; i < *row ; i++ )
{
delete [] matrix[i] ;
}
delete [] matrix ;
Answering your second question: when you allocate a 2D array with the following code
// dynamically allocate an array
matrix = new int *[row];
for (int count = 0; count < row; count++)
matrix[count] = new int[col];
you are in fact allocating one array of pointers (your matrix variable, which is a double pointer) and "row" arrays of integers (each one representing one row in your matrix, of size "col"), which are matrix[0], matrix[1], etc. up to matrix[row-1].
Thus, when you want to free your matrix, you'll first need to free every single row (the arrays allocated within the loop), and then the array which held the rows. In your case, the code you use to free your matrix is partly wrong, and should be more like the following :
// free dynamically allocated memory
for( int i = 0 ; i < row ; i++ )
{
//first we delete each row
delete [] matrix[i] ;
}
//finally, we delete the array of pointers
delete [] matrix ;
The delete within the loop will free each row of your matrix, and the final delete will free the array of rows. In your code, you use delete row times on your double pointer (matrix), which makes no sense.
Finally, using a single delete on the double pointer is wrong, because it would end up in a memory leak as you aren't freeing the memory allocated for each row, only the pointers referring to it.
Since a[b] is just *(a + b) you can of course do this:
*(*(matrix + i) + j)
Anyway, those new allocations are error prone. If one of the nested news throws then you'll have a leak. Try using std::vector instead.
Something like this would work:
int **matrix;
// dynamically allocate an array
matrix = new (std::nothrow) int *[row];
if (matrix == NULL)
{
// handle the error
}
for (int count = 0; count < row; count++)
{
*(matrix + count) = new (std::nothrow) int[col];
if (matrix[count] == NULL)
{
// handle the error
}
}
cout << "\nNow enter the element for the matrix...";
for (int i=0; i < row; i++)
{
for (int j=0; j < col; j++)
{
cout << "\nRow " << (i+1) << " Col " << (j+1) << " :";
cin >> *(*(matrix + i) + j);
}
}
Yes, you use pointer addition, but you need to understand how the memory is laid out. Say x is a pointer to the first element of an array of ints, if you want to access x[2], you can use *(x+2). However, with matrices it can get quite confusing and you're a lot more likely to access wrong indices in your matrix if you do this, so I wouldn't advise it.
You could do *(*(matrix+i)+j). It should be equivalent to bracket notation. What is happening with both notations is simply pointer arithmetic.
Related
I would like to determine if there is a way to determine whether a dynamically allocated matrix is square (nxn).
The first thing that came to mind was to see if there is a way to find out whether a pointer is about to point to an invalid memory location. But according to these posts:
C++ Is it possible to determine whether a pointer points to a valid object?
Testing pointers for validity (C/C++)
This cannot be done.
The next idea I came up with was to somehow use the sizeof() function to find a pattern with square matrices, but using sizeof() on a pointer will always yield the same value.
I start off by creating a dynamically allocated array to be of size nxn:
int **array = new int*[n]
for(int i = 0; i < n; i++)
array[i] = new int[n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
array[i][j] = 0;
}
}
Now I have a populated square matrix of size nxn. Let's say I'm implementing a function to print a square 2D array, but a user has inadvertently created and passed a 2D array of size mxn into my function (accomplished by the code above, except there are more row pointers than elements that comprise the columns, or vice versa), and we're also not sure whether the user has passed a value of n corresponding to n rows or n columns:
bool(int **arr, int n){
for(int rows = 0; rows < n; rows++)
for(int cols = 0; cols < n; cols++)
cout << *(*(arr + rows) + cols) << " ";
// Is our next column value encroaching on unallocated memory?
}
cout << endl;
// Is our next row value out of bounds?
}
}
Is there any way to inform this user (before exiting with a segmentation fault), that this function is for printing square 2D arrays only?
Edit: corrected 3rd line from
array[i] = new int[i]
to
array[i] = new int[n]
There is NO way to find out information about an allocation. The ONLY way you can do that, is to store the information about the matrix dimensions somewhere. Pointers are just pointers. Nothing more, nothing less. If you need something more than a pointer, you'll need to define a type that encapsulates all of that information.
class Matrix2D
{
public:
Matrix2D(int N, int M)
: m_N(N), m_M(M), m_data(new int[N*M]) {}
int N() const { return this->m_N; }
int M() const { return this->m_M; }
int* operator[] (int index) const
{ return m_data + m_M * index; }
private:
int m_N;
int m_M;
int* m_data;
};
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.
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;
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.
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;
}
}
}
I am a getting a segment fault when trying to input data for my array of pointers. Im pretty new to coding so any help would be great. My task was to make an array of pointers then display, swap them around and than sort them
#include <iostream>
using namespace std;
float getValueFromPointer(float* thePointer)
{
return *thePointer;
}
float* getMinValue(float* a, float* b)
{
if (*a < *b)
{
return a;
}
else
{
return b;
}
}
int main()
{
int arraySize;
cout << "Enter the array size: ";
cin >> arraySize;
float** speed = new float*[arraySize]; // dynamically allocated array
for(int i = 0; i < arraySize; i++)
{
cout << "Enter a float value: ";
cin >> *speed[i];
}
// Core Requirement 2
for (int i = 0; i < arraySize; i++)
{
float value = getValueFromPointer(*speed+i);
cout << "The value of the element " << i << " is: ";
cout << value << endl;
}
//float *pointerToMin = getMinValue(&speed[0], &speed[arraySize - 1]);
//cout << *pointerToMin << endl;
delete [] speed;
speed = NULL;
return 0;
}
You’ve only allocated space for the outer array but you need to also allocate space for each of the internal floats.
So before calling this line:
cin >> *speed[i];
You need to first allocate space for it:
speed[i] = new float;
Your problem is that you've allocated an array of float pointers. You need to allocate an array of floats. So currently you have no memory allocated for the actual floats. If you do this, you'll allocate that memory:
float *speed = new float[arraySize];
You don't have any need for a 2D/jagged array that I can see. If you start with the code above, the compiler errors should lead you right in the direction. (Basically you will start removing * from a lot of places in your code.)
EDIT
Based on your requirement that I misunderstood, a possible approach is the following. The other answer (the one that isn't mine) makes sense in broader scenarios than this, but hopefully this is sort of another angle to think about that rather arbitrary problem you're trying to solve:
int main()
{
float *pFloats = new float[10];
float **ppFloats = new float*[10];
//assign float values and pointers to them in same loop
for (int i = 0; i < 10; i++)
{
pFloats[i] = i;
ppFloats[i] = &pFloats[i];
}
//swap two arbitrary pointers
float *pTemp = ppFloats[4];
ppFloats[4] = ppFloats[5];
ppFloats[5] = pTemp;
//print our float array
for (int i = 0; i < 10; i++)
printf("%f\n", pFloats[i]);
//print our float array *through* our pointers
for (int i = 0; i < 10; i++)
printf("%f\n", *ppFloats[i]);
delete[] ppFloats;
delete[] pFloats;
}
Ignore the hard-coded constants, etc...The point here is that I've created a contiguous memory area for the floats, and then created an array of float pointers on top of it. Note that I can sort my pointer array with zero impact on the original array. There are much smarter ways to do this, but...looks like you're learning about raw pointers, so...
Contrast with the other answer which creates jagged memory for the floats (1 at a time, on demand, not necessarily contiguous).
I would like to know the main differences between a matrix stored "as a multidimensional array" in the stack and a matrix stored "as an array of pointers" in the heap.
In particular can the matrix as "multidimensional array" in the stack still be seen and used as an array of pointers?
I'm having troubles to understand why I cannot do the following: Suppose that I want to set one row of a matrix B equal to an other row of the same matrix, but I don't want to use a loop on the columns index, i.e. I don't want to set the single elements of the matrix equal to each other but move the rows directly.
Here are the three ways I tried
#include <iostream>
using namespace std;
int main() {
int xsize=3, ysize=3;
int row1, row2;
int B[][3]={{1,2,3},{4,5,6},{7,8,9}};
cout << "Row to change?";
cin >> row1 ;
cout << "Which row must it be set equal to?";
cin >> row2 ;
//1): set the two rows equal directly:
B[row1 - 1] = B[row2 - 1];
//gives error : "invalid array assignment"
//------------------------------------------------------------------------
//2) create copy on the heap and set the row of B equal to the row of matrix
int ** matrix = new int*[ysize];
for(int i = 0; i < ysize; i++) {
matrix[i] = new int[xsize];
}
for(int i = 0; i < ysize; i++) {
for(int j = 0; j < xsize; j++) {
matrix[i][j]=B[i][j];
}
B[row1 - 1] = matrix[row2 - 1];
//gives the error "incompatible types in assignment of 'int*' to 'int [3]"
//------------------------------------------------------------------------
//3) the same as 2) but reversed
matrix[row1 - 1] = B[row2 - 1];
//this one works, so that I can print the matrix modified
for(int i = 0; i < ysize; i++) {
for(int j = 0; j < xsize; j++) {
cout << matrix[i][j] << " ";
}
cout << "\n";
}
}
I can't understand why 1) and 2) do not work, while 3) does. What is exaclty the difference if I reverse the equality in 2) (which I did in 3)) and why does it work only in that way?
I thought that a matrix can be seen as an array of pointers anyway, since if I print something like cout << B[1]; gives me the memory index of the first element of second row, which is an array, so B[1] should behave like a pointer to the second row.
Also is there a more correct way to move or copy rows of a matrix (again without using a loop on the columns)?
One of the quirks of C is that multi-dimensional arrays are hard to work with. Most beginners' books introduce them in the same chapter as 1D arrays, before the reader is ready to understand some of the subtle difficulties.
One of those subtle difficulties is that the syntax
mtx[i][j]
can refer to a 2D array, or it can refer to a double pointer. If it refers to a double pointer, mtx is a type **, and holds a list of pointers to 1D arrays, which are the rows of the matrix. Note that the matrix can be ragged, something that isn't allowed with true 2D arrays in C.
To answer your question, in reality if mtx is a type **, we will construct it on the heap. You can construct it on the stack but only by coding round the type system. A true matrix can be on the heap or on the stack, but the syntax for creating one on the heap is anther of the subtle difficulties of 2D matrices in C.
i have a quite weird question which probably has no practical use but the answers bothers me a lot. I tried to mess around today a little bit with arrays and how they are allocated in memory using this code: (Compiler Xcode 4 btw, 4 byte integer)
int ***c;
int size_x = 0;
int size_y = 0;
int size_z = 0;
cout << "Enter x: " << endl;
cin >> size_x;
cout << "Enter y: " << endl;
cin >> size_y;
cout << "Enter z: " << endl;
cin >> size_z;
c = new int**[size_x];
for (int i = 0; i < size_x; ++i) {
*(c+i) = new int*[size_y];
for (int j = 0; j < size_y; ++j) {
*(*(c+i)+j) = new int[size_z];
}
}
for (int i = 0; i < size_x; ++i) {
for (int j = 0; j < size_y; ++j) {
for (int k = 0; k < size_z; ++k) {
cout << (*(*(c+i)+j)+k) << endl;
//cout << &c[i][j][k] << endl;
}
}
}
delete [] c;
When i enter now: 3, 2 and 4 i get the following output in the console:
0x100100a60
0x100100a64
0x100100a68
0x100100a6c
0x100100a70
0x100100a74
0x100100a78
0x100100a7c
0x100100a90
0x100100a94
0x100100a98
0x100100a9c
0x100100aa0
0x100100aa4
0x100100aa8
0x100100aac
0x100100ac0
0x100100ac4
0x100100ac8
0x100100acc
0x100100ad0
0x100100ad4
0x100100ad8
0x100100adc
What my question is now, if we look at the output, than we see that mostly, the memory is aligned every 4 bytes but sometimes we see a bigger step like from 0x100100a7c to
0x100100a90 .
Is this normal and how can i prevent this? Why is this? Is there a possibility to force c to align my memory as a constant line? (I'm not native english so sorry for that but i don't know how to say it better)
Its just for general understanding :-)
Thank u!
P.S. is it enough to use delete [] once btw or do i have to go through each of the 3 memory blocks and delete [] there the whole array? EDIT:
I delete memory now like this and it works pretty good:
cout << "Free Memory" << endl;
for (int i = 0; i < m_sx; ++i) {
for (int j = 0; j < m_sy; ++j) {
delete [] m_array[i][j];
//delete [] (*(*(m_array)+j)+k);
}
delete [] m_array[i];
}
delete [] m_array, m_array = NULL;
Yes, this is normal. The memory is aligned, btw., it's just not contiguous because subsequent calls to new do not make this guarantee. And yes, you can allocate the entire 3-d array in a single, contiguous buffer:
int *A = new int[size_x * size_y * size_z];
or, safer
std::vector<int> A(size_x * size_y * size_z);
and then index it with
int element = A[i * size_z * size_y + j * size_z + k]
to get the element at (i,j,k).
This is, in fact, very useful, as it gives you multidimensional arrays with little overhead, preserving locality of reference and preventing indirection. Also, the error handling for this allocation scheme is much simpler so you run less of a risk of memory leaks. Any good matrix library will be implemented this way. For C++, that includes Boost.MultiArray.
As for deallocation: yes, you need multiple calls to delete[] in your present scheme.
Heres a routine which allocates the 3D array of dimension N1 x N2 x N3 in contiguous memory space while allowing you the a[i][j][k] syntax for operator access. The array is dynamic but continuous so it's a huge plus over the vector<> approach and loops of new[] calls.
template <class T> T ***Create3D(int N1, int N2, int N3)
{
T *** array = new T ** [N1];
array[0] = new T * [N1*N2];
array[0][0] = new T [N1*N2*N3];
int i,j,k;
for( i = 0; i < N1; i++) {
if (i < N1 -1 ) {
array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);
array[i+1] = &(array[0][(i+1)*N2]);
}
for( j = 0; j < N2; j++) {
if (j > 0) array[i][j] = array[i][j-1] + N3;
}
}
cout << endl;
return array;
};
template <class T> void Delete3D(T ***array) {
delete[] array[0][0];
delete[] array[0];
delete[] array;
};
And later in your implementation routine...
int *** array3d;
int N1=4, N2=3, N3=2;
int elementNumber = 0;
array3d = Create3D<int>(N1,N2,N3);
cout << "{" << endl;
for (i=0; i<N1; i++) {
cout << "{";
for (j=0; j<N2; j++) {
cout << "{";
for (k=0; k<N3; k++) {
array3d[i][j][k] = elementNumber++;
cout << setw(4) << array3d[i][j][k] << " ";
}
cout << "}";
}
cout << "}";
cout << endl ;
}
cout << "}" << endl;
Delete3D(array3d);
Gives the output:
{
{{ 0 1 }{ 2 3 }{ 4 5 }}
{{ 6 7 }{ 8 9 }{ 10 11 }}
{{ 12 13 }{ 14 15 }{ 16 17 }}
{{ 18 19 }{ 20 21 }{ 22 23 }}
}
Since this is tagged C, here is also a C answer. Since C99 multidimensional arrays can be handled quite efficiently, even if the sizes are dynamic:
double c[size_x][size_y][size_z];
This allocates the matrix contiguously on the stack. Matrix elements are accessed by c[i][j][k] and the compiler does all the indexing arithmetic for you. If you fear that this could lead to SO, you can easily call malloc with it:
double (*c)[size_y][size_z] = malloc(sizeof(double[size_x][size_y][size_z]));
The issue is not that your memory isn't aligned ... the requirement by the C++ specification for a call to new and new[] is that it passes back a pointer pointing to contiguous memory that is properly aligned for the platform and the size of the object requested.
Your problem is that you are not allocating the entire buffer for the array with a single call to new[], but rather with multiple calls to new[]. Therefore while each call to new will return aligned and contiguous memory, the multiple calls to new[] are not required to return memory buffers that themselves are contiguously allocated. For example, each call to new[] returns aligned memory, but as you noted, there can be "gaps" in the start of each memory array that new returns. The reason for these "gaps" can have multiple reasons, and really depends on how the underlying OS is allocating memory for your program.
If you do not want to have any "gaps" in each array, then you will need to allocate the entire buffer with a single call to new.
Finally, to answer your question about delete[], yes, because you did not allocate the entire memory buffer with a single call to new[], you cannot delete your array with a single call to delete[]. Every call to new[] must be paired with a call to delete[] since those were separate memory allocations.
Yes this is normal.
You allocate data row by row; The only thing you can be sure is that data will be contiguous on each row.