How to init a double**? - c++

I need to init/use a double ** (decleared in my header):
double **pSamples;
allocating (during the time) a matrix of NxM, where N and M are get from two function:
const unsigned int N = myObect.GetN();
const unsigned int M = myObect.GetM();
For what I learnt from heap and dynamic allocation, I need keyword new, or use STL vector, which will manage automatically allocate/free within the heap.
So I tried with this code:
vector<double> samplesContainer(M);
*pSamples[N] = { samplesContainer.data() };
but it still says I need a constant value? How would you allocate/manage (during the time) this matrix?

The old fashioned way of initializing a pointer to a pointer, is correctly enough with the new operator, you would first initialize the the first array which is a pointer to doubles (double*), then you would iterate through that allocating the next pointer to doubles (double*).
double** pSamples = new double*[N];
for (int i = 0; i < N; ++i) {
pSambles[i] = new double[M];
}
The first new allocates an array of double pointers, each pointer is then assigned to the array of pointers allocated by the second new.
That is the old way of doing it, remember to release the memory again at some point using the delete [] operator. However C++ provide a lot better management of sequential memory, such as a vector which you can use as either a vector of vectors, or simply a single vector capable of holding the entire buffer.
If you go the vector of vector way, then you have a declaration like this:
vector<vector<double>> samples;
And you will be able to reference the elements using the .at function as such: samples.at(2).at(0) or using the array operator: samples[2][0].
Alternatively you could create a single vector with enough storage to hold the multidimensional array by simply sizing it to be N * M elements large. However this method is difficult to resize, and honestly you could have done that with new as well: new double[N * M], however this would give you a double* and not a double**.

Use RAII for resource management:
std::vector<std::vector<double>> samplesContainer(M, std::vector<double>(N));
then for compatibility
std::vector<double*> ptrs(M);
for (std::size_t i = 0; i != M; ++i) {
ptrs[i] = samplesContainer[i].data();
}
And so pass ptrs.data() for double**.

samplesContainer.data() returns double*, bur expression *pSamples[N] is of type double, not double*. I think you wanted pSamples[N].
pSamples[N] = samplesContainer.data();

Related

How to dynamically create a c++ array with known 2nd dimension?

I have a function:
void foo(double[][4]);
which takes a 2d array with 2nd dimension equal to 4. How do I allocate a 2d array so that I can pass it to the function? If I do this:
double * arr[4];
arr = new double[n][4];
where n is not known to the compiler. I cannot get it to compile. If I use a generic 2d dynamic array, the function foo will not take it.
As asked, it is probably best to use a typedef
typedef double four[4];
four *arr; // equivalently double (*arr)[4];
arr = new four[n];
Without the typedef you get to be more cryptic
double (*arr)[4];
arr = new double [n][4];
You should really consider using standard containers (std::vector, etc) or containers of containers though.
typedef double v4[4];
v4* arr = new v4[n];
Consider switching to arrays and vectors though.
I know it may not be what OP has intended to do, but it may help others that need a similar answer.
You are trying to make a dynamic array of statically success array. The STL got your solution: std::vector and std::array
With these containers, things are easy easier:
std::vector<std::array<int, 4>> foo;
// Allocate memory
foo.reserve(8);
// Or instead of 8, you can use some runtime value
foo.reserve(someSize);
// Or did not allocated 8 + someSize, but ensured
// that vector has allocated at least someSize
// Add entries
foo.push_back({1, 2, 3, 4});
// Looping
for (auto&& arr : foo) {
arr[3] = 3;
}
// Access elements
foo[5][2] = 2;
Alternatively to creating a new type and occupying a symbol, you can create a pointer to pointer, and do it like that:
double **arr = new double*[j];
for (int i = 0; i < j; ++i)
{
arr[i] = new double[4];
}
whereas j is the int variable that holds the dynamic value.
I've written a simple code that shows it working, check it out here.

How to create a pointer to pointers

The problem that I have is to create a specific matrix.
I have to use an array called for example ptr with x pointers. Each pointer in this array should point to a new array (in this case, an int array; each array is a new line in the matrix then).
All x arrays should be created with new; in the end, it should be possible to access the matrix with ptr[a][b] easily.
After a lot of trying and failing, I hope that someone can help me out.
Thank you in advance!
Since this is obviously homework, let me give you a better answer for your sake to go alongside the accepted one.
std::vector<std::vector<int>> matrix(10, std::vector<int>(10));
// ^ ^ ^
// Column count ______| |________________|
// |
// |___ Each column is
// initialized with
// a vector of size 10.
That's a 10x10 matrix. Since we're using vectors, the sizes are dynamic. For statically sized arrays, you can use std::array if you want. Also, here's the reference for std::vector.
If the number of pointers in the array is known, you could simply use a raw array of pointers to int:
int* my_array[10]; // 10 int*
Then you should allocate memory individually for each pointer in the array using usually a for loop:
for(int i=0; i<10; i++){
// each int* in the array will point to an area equivalent to 10 * sizeof(int)
my_array[i] = new int[10];
}
On the other hand, if you don't know the size of the array, then you need a pointer to pointers:
int** ptr_to_ptr = new int*[10];
Note that I am allocating space for 10 int* and not int.
Remember to deallocate the memory allocated above also for the internal pointers, once you don't need that memory anymore.

initialize an int[][] with new()

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.

2D Vectors/Dynamic Arrays

I'm trying to work with 2D arrays in order to keep track of some objects that are laid out in a grid fashion. I would like each element of the of the 2d array to contain an Object*. Object being a class I have defined. However working with these things isn't exactly easy.
This is the my method for filling the 2D array with Object pointers:
int xDim;
//how far to go in the x direction
//x's Dimension that is
Object *** test; //the highest level pointer used
test = new Object ** [xDim];
//add horizontal array of Object **
for(int fillPos=0; fillPos < xDim; fillPos++){
//point each Object ** to a new Object * array
//add column arrays
test[fillPos] = new Object*[zDim];
}
My intention is then to use this array's Object pointers to point to the child class of Object, say childObj. My intent is to use them in this way.
for (int xPos=0; xPos < xDim; xPos++){
for(int zPos=0; zPos < zDim; zPos++){
//pointing each Object * in the 2D array to
//a new childObj
test[xPos] [zPos] = new childObj;
}
}
I realize this could potentially be a real hassle in terms of memory. I'm asking if this is a nice way to handle such a situation. Could perhaps something like
vector< <vector<Object*> > work better? Would vectors manage the deletion nicely so as to avoid memory leaks? Or perhaps I would simply have to loop through the vector and call delete on each Object* before getting rid of the vectors themselves?
So, should I use arrays as I have or vectors? What could be some problems associated with each method?
Using Object *** requires that you go through and delete each Object Pointer, each Array of Object Pointers, and then the finally delete the outermost Array of Object**, in that order. In my opinion this leaves a lot of room for carelessness and mistakes.
for (int xPos=0; xPos < xDim; xPos++) {
for (int zPos=0; zPos < zDim; zPos++) {
delete test[xPos][yPos]; // delete the object ptr
}
delete[] test[xPos]; // delete each array of object ptr
}
delete[] test; // delete the array of array of object ptrs
I would much rather prefer the vector approach, because the vectors are locally scoped. Dynamic allocation can be rather expensive and should be avoided if possible.
So for the vector approach, you would only need to delete the Object ptrs. (A good rule of thumb is that every call to new requires a corresponding call to delete).
vector<vector<Object*>> matrix;
... // some code here
for each (vector<Object*> vec in matrix)
for each (Object* oPtr in vec)
delete oPtr;
If you knew the size of your 2-D array at compile-time, you could achieve the same effect of avoiding memory management for the 2-D array, and simply manage the Object pointers.
Object * matrix[xDim][yDim]; // xDim and yDim are compile-time constants
But I still like vectors because they have the added benefit of being able to resize themselves dynamically unlike arrays, so you won't have to worry about knowing the size upfront.

Multi-dimensional array and pointers in C++?

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++?