I'm hitting an odd segmentation fault that is happening somewhere and I was wondering whether it could be due to the way I allocated the matrix array of pointers.
It's declared as such in the .h file:
int **matrix;
But when I pass it, I am using it in this way int *matrix[], in order to
access individual rows with matrix[i] (this made a lot of my tasks simpler).
So, when I am allocating the matrix, should I have done:
matrix = new int * [vertices];
for (int i = 0; i < vertices; i++)
matrix[i] = new int[vertices];
Or for the third line, should I use the -> operator:
matrix[i]-> new int[vertices]; // Or something like this.
And what is the difference between the two?
The first option you suggested is completely fine in this case. But the second one with the -> operator is not even a valid syntax. The first line from the first suggestion actually creates an array of int* of size vertices:
matrix = new int * [vertices];
Each of the elements of this array is initialised with some garbage values. You can make sure it is initialised with zero by using braces like this: new int * [vertices](). But in either case accessing any of the pointers by matrix[i]-> would be meaningless. In fact the arrow operator -> is a dereference operator that is used exclusively with pointers to objects that have members. Hope that helps.
Related
What is the best way to allocate memory for an n-dimensional array in c++ at runtime? I am trying to read a matrix of values from a file, and depending on which file I read, the matrix could be any size. However, once the matrix is created, its size is static.
Since I don't know at compile-time what the size will be, I can't define it as int[a][b], so I was experimenting with using pointers to pointers like int**, but when I declare int** arr; arr[0][0] = 1 I get an error. I've experimented with other solutions as well. For example, I tried using one of the answers to Determine array size in constructor initializer, using int* arr; arr = new int[a], but it doesn't seem to work once I try to use it for two dimensions. Granted, I could be using it incorrectly, but the following block of code gives me a segfault:
int** arr;
(*arr) = new int[a];
edit: And of course, right after I ask the question, I find something semi-suitable in Need help regarding Dynamic Memory Allocation for two dimensional arrays in C++. I'd prefer not to do it this way, but it's definitely doable.
You would do it something like this (stolen from this answer):
int** ary = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
ary[i] = new int[sizeY];
Alternatively, you can do this:
int *ary = new int[sizeX*sizeY];
// ary[i][j] is then rewritten as
ary[i*sizeY+j]
It might remove the headache of pointer indirection.
I have a for-loop that needs to incrementally add columns to a matrix. The size of the rows is known before entering the for-loop, but the size of the columns varies depending on some condition. Following code illustrates the situation:
N = getFeatureVectorSize();
float **fmat; // N rows, dynamic number of cols
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
float *fv = new float[N];
getObjectFeatureVector(fv);
// How to add fv to fmat?
}
}
Edit 1 This is how I temporary solved my problem:
N = getFeatureVectorSize();
float *fv = new float[N];
float *fmat = NULL;
int col_counter = 0;
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
getObjectFeatureVector(fv);
fmat = (float *) realloc(fmat, (col_counter+1)*N*sizeof(float));
for(int r=0; r<N; r++) fmat[col_counter*N+r] = fv[r];
col_counter++;
}
}
delete [] fv;
free(fmat);
However, I'm still looking for a way to incrementally allocate memory of a two-dimensional array in C/C++.
To answer your original question
// How to add fv to fmat?
When you use float **fmat you are declaring a pointer to [an array of] pointers. Therefore you have to allocate (and free!) that array before you can use it. Think of it as the row pointer holder:
float **fmat = new float*[N];
Then in your loop you simply do
fmat[i] = fv;
However I suggest you look at the std::vector approach since it won't be significantly slower and will spare you from all those new and delete.
better - use boost::MultiArray as in the top answer here :
How do I best handle dynamic multi-dimensional arrays in C/C++?
trying to dynamically allocate your own matrix type is pain you do not need.
Alternatively - as a low-tech, quick and dirty solution, use a vector of vectors, like this :
C++ vector of vectors
If you want to do this without fancy data structures, you should declare fmat as an array of size N of pointers. For each column, you'll probably have to just guess at a reasonable size to start with. Dynamically allocate an array of that size of floats, and set the appropriate element of fmat to point at that array. If you run out of space (as in, there are more floats to be added to that column), try allocating a new array of twice the previous size. Change the appropriate element of fmat to point to the new array and deallocate the old one.
This technique is a bit ugly and can cause many allocations/deallocations if your predictions aren't good, but I've used it before. If you need dynamic array expansion without using someone else's data structures, this is about as good as you can get.
To elaborate the std::vector approach, this is how it would look like:
// initialize
N = getFeatureVectorSize();
vector<vector<float>> fmat(N);
Now the loop looks the same, you access the rows by saying fmat[i], however there is no pointer to a float. You simply call fmat[i].resize(row_len) to set the size and then assign to it using fmat[i][z] = 1.23.
In your solution I suggest you make getObjectFeatureVector return a vector<float>, so you can just say fmat[i] = getObjectFeatureVector();. Thanks to the C++11 move constructors this will be just as fast as assigning the pointers. Also this solution will solve the problem of getObjectFeatureVector not knowing the size of the array.
Edit: As I understand you don't know the number of columns. No problem:
deque<vector<float>> fmat();
Given this function:
std::vector<float> getObjectFeatureVector();
This is how you add another column:
fmat.push_back(getObjectFeatureVector());
The number of columns is fmat.size() and the number of rows in a column is fmat[i].size().
I am a c++ newbie. While learning I came across this.
if I have a pointer like this
int (*a)[2][3]
cdecl.org describe this as declare a as pointer to array 2 of array 3 of int:
When I try
int x[2][3];
a = &x;
this works.
My question is how I can initialize a when using with new() say something like
a = new int [] [];
I tried some combinations but doesn't get it quite right.
Any help will be appreciated.
You will have to do it in two steps - first allocate an array of pointers to pointers(dynamically allocated arrays) and then, allocate each of them in turn. Overall I believe a better option is simply to use std::vector - that is the preferred C++ way of doing this kind of things.
Still here is an example on how to achieve what you want:
int a**;
a = new int*[2];
for (int i =0; i< 2;++i){
a[i] = new int[3]
}
... use them ...
// Don't forget to free the memory!
for (int i = 0; i< 2; ++i) {
delete [] a[i];
}
delete [] a;
EDIT: and as requested by Default - the vector version:
std::vector<std::vector<int> > a(2, std::vector<int>(3,0));
// Use a and C++ will take care to free the memory.
It's probably not the answer you're looking for, but what you
need is a new expression whose return type is (*)[2][3] This
is fairly simple to do; that's the return type of new int
[n][2][3], for example. Do this, and a will point to the
first element of an array of [2] of array of [3] int. A three
dimensional array, in sum.
The problem is that new doesn't return a pointer to the top
level array type; it returns a pointer to the first element of
the array. So if you do new int[2][3], the expression
allocates an array of 2 array of 3 int, but it returns
a pointer to an array of 3 int (int (*a)[3]), because in C++,
arrays are broken (for reasons of C compatibility). And there's
no way of forcing it to do otherwise. So if you want it to
return a pointer to a two dimensional array, you have to
allocate a three dimensional array. (The first dimension can be
1, so new [1][2][3] would do the trick, and effectively only
allocate a single [2][3].)
A better solution might be to wrap the array in a struct:
struct Array
{
int data[2][3];
};
You can then use new Array, and everything works as expected.
Except that the syntax needed to access the array will be
different.
int *x = new int[5]();
With the above mentality, how should the code be written for a 2-dimensional array - int[][]?
int **x = new int[5][5] () //cannot convert from 'int (*)[5]' to 'int **'
In the first statement I can use:
x[0]= 1;
But the second is more complex and I could not figure it out.
Should I use something like:
x[0][1] = 1;
Or, calculate the real position then get the value
for the fourth row and column 1
x[4*5+1] = 1;
I prefer doing it this way:
int *i = new int[5*5];
and then I just index the array by 5 * row + col.
You can do the initializations separately:
int **x = new int*[5];
for(unsigned int i = 0; i < 5; i++)
x[i] = new int[5];
There is no new[][] operator in C++. You will first have to allocate an array of pointers to int:
int **x = new int*[5];
Then iterate over that array. For each element, allocate an array of ints:
for (std::size_t i = 0; i < 5; ++i)
x[i] = new int[5];
Of course, this means you will have to do the inverse when deallocating: delete[] each element, then delete[] the larger array as a whole.
This is how you do it:
int (*x)[5] = new int[7][5] ;
I made the two dimensions different so that you can see which one you have to use on the lhs.
Ff the array has predefined size you can write simply:
int x[5][5];
It compiles
If not why not to use a vector?
There are several ways to accomplish this:
Using gcc's support for flat multidimensional arrays (TonyK's answer, the most relevant to the question IMO). Note that you must preserve the bounds in the array's type everywhere you use it (e.g. all the array sizes, except possibly the first one), and that includes functions that you call, because the produced code will assume a single array. The allocation of $ new int [7][5] $ causes a single array to be allocated in memory. indexed by the compiler (you can easily write a little program and print the addresses of the slots to convince yourself).
Using arrays of pointers to arrays. The problem with that approach is having to allocate all the inner arrays manually (in loops).
Some people will suggest using std::vector's of std::vectors, but this is inefficient, due to the memory allocation and copying that has to occur when the vectors resize.
Boost has a more efficient version of vectors of vectors in its multi_array lib.
In any case, this question is better answered here:
How do I use arrays in C++?
Greetings again, and thanks once more to all of you who provided answers to the first question. The following code is updated to include the two functions per the assignment.
To see the original question, click here.
I am pretty sure this fulfills the requirements of the assignment, but once again I would greatly appreciate any assistance. Did I modify the delete statements appropriately? Thanks again.
#include<iostream>
#include<string>
int** createArray(int, int);
void deleteArray(int*[], int);
using namespace std;
int main()
{
int nRows;
int nColumns;
cout<<"Number of rows: ";
cin>>nRows;
cout<<"Number of columns: ";
cin>>nColumns;
int** ppInt = createArray(nRows, nColumns);
deleteArray(ppInt, nRows);
}
int** createArray(int nRows, int nColumns)
{
int** ppInt = new int*[nRows];
for (int nCount = 0; nCount < nRows; nCount++)
{
ppInt[nCount] = new int[nColumns];
}
return ppInt;
}
void deleteArray(int** nPointer, int nRows)
{
for (int nCount = 0; nCount < nRows; nCount++)
{
delete[] nPointer[nCount];
}
delete[] nPointer;
}
P.S. Here is the assignment documentation itself, in case it helps:
(1) Design and implement a function to allocate memory for a 2-D integer array: the function is supposed to take two integers as parameters, one for number of rows and one for number of columns. You need to use “new” operator in this function. Remember that we need to first create an array of pointers. Then, for each pointer in that array, we need to create an array of integers. This function is supposed to return a pointer which points to a 2-D integer array.
(2) Design and implement a function to de-allocate memory for this 2-D array: the function is supposed to have two parameters (a pointer which points to a 2-D integer array, and the other one is number of rows in the array). In the function, you are supposed to de-allocate memory for this 2-D array using the “delete” operator. You should delete each row (an array of integers) first, and then delete the array of pointers.
The code looks good.
However, there are some problems you may want to address, for us humans:
Your function signatures (declarations) lack parameter names. More suitable:
int** createArray(int rows, int columns);
void deleteArray(int** array, int rows);
Your function names aren't too descriptive as to what they really create/delete. create2DArray would be a wiser choice, for example.
Your n prefixes to your variables hurt my eyes. numRows or rowCount is more readable.
Similarly, ppInt is crazy. Try array (for nPointer as well, for consistency). (Sadly, you can't write 2dArray.)
Using i as a loop counter is more common than nCount or similar (especially for array indexes). I suggest you use that instead.
Some things which go Above And Beyond, for your personal practice:
Create a class which takes rows and cols as arguments to its constructor. Make sure to deallocate the array automatically.
Use std::vector and create a resize member function for your class. Note that this deviates from the original question, which asked for pointers.
Create a copy function and a clone function to copy data to another 2D array (possibly of a different size!) or clone an existing array.
Its OK.
The problem is that you are not thinking about exception safety in your code.
int** ppInt = new int*[nRows]; // ALLOC 1
for (int nCount = 0; nCount < nRows; nCount++)
{
ppInt[nCount] = new int[nColumns]; // ALLOC 2
}
Say ALLOC 1 goes fine.
But if any of the ALLOC 2 fail then you have an exception and a severe memory leak.
For example.
You fail on the fourth call to ALLOC 2. Then you leak the memory from ALLOC 1 and the first three calls to ALLOC 2. Now in your situation the code is so trivial it probably does not matter. BUT this is the kind of thing you should always keep in mind when writting C++ code.
What will happen here if an exception is throw, what resources are going to be leaked what resources are not going to be cleaned up correctly.
I think you should think about wrapping your 2D array inside a class so that you can guarantee that memory is allocated and de-allocated correctly even in the presence of exceptions.
Looks reasonable to me.
I'm not sure about submitting a whole new question, though. It might have been better as an amendment to the original.
For "deleteArray", your prototype and definition aren't exactly the same:
void deleteArray(int*[], int);
void deleteArray(int** nPointer, int nRows)
They do have the same meaning, but for clarity I think it would be best to have them exactly the same (favoring `int**' to emphasize the fact that you're passing pointers) for consistency.
Also, include the argument names in the prototype.