Incrementally dynamic allocation of memory in C/C++ - c++

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().

Related

Creating bidimensional array's size with the input values

First of all, happy new year!
So, I'd like to ask if I could use some input values as the size of a bidimensional array, for example:
I'd like to know, if instead of doing this:
const int N = 10;
const int M = 10;
typedef int IntMatrix[N][M];
Let's say that would be the max size of the array I could create, but then the user inputs that the size must have a size of 5x5. I know I could then use 5x5 as a limit when doing stuff, but could I do like the same, but using the input values as the dimension of the Matrix?
Something like:
cin >> N >> M;
And then use that as the MAX size of each dimension.
Thanks for your help!
No. The size of an array must be known at compile time and can not be determined at runtime as described in this tutorial for example. Therefore, the size of the array cannot depend on user input.
What you can do, is allocate an array dynamically and store it's address in a pointer. The size of a dynamic array can be determined at runtime. However, there is a problem. Only the outermost dimension of a dynamically allocated 2D array may be determined at runtime. You have 2 options: Either you allocate a flat array of size NxM where the rows are stored continuously one after the other and you calculate the index using maths. Or, you use an array of pointers and assign each pointer to a dynamically allocated array column. The first option is more efficient.
There is another problem. Dynamic memory management is hard, and it's never a good idea to do it manually even if you know what you're doing. Much less if you don't. There is a container class in the standard library which takes care of memory management of dynamic arrays. It's std::vector. Always use it when you need a dynamic array. Your options stay similar. Either use a flat, NxM size vector, or a vector of vectors.
The array should be dynamically allocatedn because array size should be known at compile-time. You can do this way:
int N,M; // Dimensions
int** intMatrix; // Array of array
std::cin << N << M;
intMatrix = new int*[N]; // Allocate N the row
for(int i=0; i<N; i++){
intMatrix[i] = new int[M]; // For each row, allocate the col
}
// aaaand don't forget to free memory like this:
for(int i=0; i<N; i++){
delete [] intMatrix[i];
}
delete [] intMatrix;

C++ How to create a dynamic array of vectors?

I'm having problem initialising an array of std::vectors.
I'm declaring and initialising it like this:
vector<component_change*>* _changes;
_changes = new vector<component_change*> [numThreads];
in the hope that it's in the same form as this:
int * foo;
foo = new int [5];
but when I hit a breakpoint after the initialisation, _changes' size is 0.
What am I doing wrong and how can I fix it?
I don't want to use a vector of vectors as the number I need remains constant throughout the program but depends on the current hardware. And I'm not just looking for a single vector (Each vector will be used by a different thread then merged when the threads have finished their tasks).
Thanks guys! :)
Your program is correct. But you misinterpreted the debugger. _changes's size is not 0, but the first vector in your array (the one _changes points at) is empty. Thats because the debugger does not know if _changes points at a single element or an array (in that case the compiler would not know how many elements are in that array). Simply use a vector and call std::vector::shrink_to_fit.
If the size can be determined at compile time use a std::array. If the size is a run-time argument then use a vector and don't change the size of the container.
Are you interested in have a vector for each thread, or a vector containing items used by each thread? I assumed the later, but my answer could be adapted.
This is using a statically sized array; (this syntax is close).
const int NUMBER_OF_THREADS = 5;
component_change* _changes[NUMBER_OF_THREADS] =
{
new component_change(1),
new component_change(2),
new component_change(3),
new component_change(4),
new component_change(5)
}
If the number of threads is dynamic, you will have to use a new...
int NUMBER_OF_THREADS = system.getThreadCount();
component_change* _changes = new component_change[NUMBER_OF_THREADS];
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
_changes[i] = new component_change(i+1);
}
If you want to a std::vector:
int NUMBER_OF_THREADS = system.getThreadCount();
std::vector<component_change*> _changes;
_changes.reserve(NUMBER_OF_THREADS);
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
_changes.push_back(new component_change(i+1));
}
I think you're kind of mislead, this size that you are reading belongs to the vector in the first element of the array. Its size is equal to 0 since no elements have been inserted in the vector yet.
new vector is usually wrong.
You should use, with most preferred if possible first,
std::vector<component_change> _changes(numThreads);
or
std::vector<std::unique_ptr<component_change>> _changes(numThreads);
or
std::vector<component_change*> _changes(numThreads);
or if each element of the vector should itself contain an array of components (it's not clear in your question)
std::vector<std::vector<**component_change**>> _changes(numThreads);
Declaring the component as one of the above ways, depending on your needs.
Note that the pointers begin not pointing to anything. You'd have to allocate the individual components as a separate step.
The following creates an array of numThreads vectors, not a vector of numThread elements.
new vector<component_change*> [numThreads]

Arbitrary Dimensional Array

So I'm trying to create an n-dimensional array structure for use in a maze generating program.
I've simplified my problem (for the purposes of trying to get the theory figured out before making it templatized and adding all the necessary helper functions)
So my problem currently boils down to wanting to make an ArbitraryArray class that takes in an argument to its constructor specifying the number of dimensions. Each dimension will have length = 5. (for now)
This is what I have so far:
class ArbitraryArray{
public:
int array[5];
ArbitraryArray*subArray;
ArbitraryArray(){}
ArbitraryArray(int depth){
if (depth == 2) subArray = new ArbitraryArray[5];
else if (depth > 2) for (int i = 0; i < 5; i++) subArray = new ArbitraryArray(depth - 1);
}
};
And I'd create a 2 dimensional object like so:
ArbitraryArray testArray(2);
Or a 3 dimensional object like so:
ArbitraryArray testArray(3);
Problem is, when I tested it for depth = 3 and then tried to set an integer value, via:
testArray.subArray[3].subArray[4].array[4] = 7;
I received a runtime error, leading me to believe that I'm doing something wrong in how I allocate these objects dynamically.
Also, I included an empty default constructor since that gets called by lines like:
subArray = new ArbitraryArray[5];
I'm aware this may not be the best way to go about creating an arbitrary dimensional array data structure, but I'd really like to figure out why this implementation is not working before potentially looking for better methods.
Also I am aware I shouldn't have a line like:
int array[5];
And that it should be a pointer instead so that there isn't a ton of wasted memory allocation for all the levels of the array above the bottom dimension. And I intend to modify it to that after I get this basic idea working.
How about using std::vector for allocating the correct amount of blank memory, which would be
sizeof(T) * dim1 * dim2 * dim3 * ...
Then write a helper class which takes care of the indexing, i.e., it will compute i from given (x,y,z,...), whatever many dimensions you might have.
The beauty of this approach, IMHO, lies in not having to fiddle with pointers, and the helper class simply implements an indexing scheme of your preference (row major or column major).
EDIT
When using std::valarray, things may become easier, as you can use std::slice and/or std::gslice to calculate your indexing for you.
Haven't compiled anything, just visual inspection. What about this:
template<int array_length>
class ArbitraryArray{
public:
int array[array_length];
ArbitraryArray ** subArray;
ArbitraryArray(){}
ArbitraryArray(int depth){
if (depth == 1)
subArray = 0;
else {
subArray = new ArbitraryArray*[array_length];
for (int i = 0; i < array_length; i++)
subArray[i] = new ArbitraryArray(depth - 1);
}
}
};
Well, for once, if depth is greater than 2, you create five ArbitraryArrays, but you save all their pointers in one SubArray pointer. SubArray needs to be an array of pointers to ArbitraryArrays, try ArbitraryArray *subArray[5]; and for (int i = 0; i < 5; i++) subArray[i] = new ArbitraryArray(depth - 1) and see what happens.
In your example you are creating an array that is all over the place in memory instead of one array that is stored in a continuous block of memory. This could cause some issues depending on you handle the memory. e.g. using memcpy on it will never work.
I think a little more flexible approach would be create one large array and instead have an index into the array based on the number of dimensions
int n = static_cast<int>(pow( 5.0, static_cast<double>(depth) ));
Type* a = new Type[ n ];
i.e. since you base your array size on 5, a 2-dim size would be 5x5 and a 3-dim 5x5x5
to access an element in the array say a[2,2,3] (0-based) it could be calculated as
a[2*5*5 + 2*5 + 3]
Just use the Boost multi_array class. It is very flexible, efficient and can perform bounds checking.
Boost Multi-Array

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

pointer arithmetic on vectors in c++

i have a std::vector, namely
vector<vector<vector> > > mdata;
i want pass data from my mdata vector to the GSL function
gsl_spline_init(gsl_spline * spline, const double xa[], const double ya[], size_t size);
as ya. i already figured out that i can do things like
gsl_spline_init(spline, &(mgrid.front()), &(mdata[i][j][k].front()), mgrid.size());
this is fine if i want to pass the data from mdata for fixed i,j to gsl_spline_init().
however, now i would need to pass along the first dimension of mdata, so for fixed j,k.
i know that for any two fixed indices, all vectors along the remaining dimensions have the same length, so my vector is a 'regular cube'. so the offset between all the values i need should be the same.
of course i could create a temporary vector
int j = 123;
int k = 321;
vector<double> tmp;
for (int i = 0: i < mdata.size(); i++)
tmp.push_back(mdata[i][j][k]);
gsl_spline_init(spline, &(mgrid.front()), &(tmp.front()), mgrid.size());
but this seems too complicated. perhaps there is a way to achieve my goal with pointer arithmetic?
any help is greatly appreciated :)
You really can't do that without redesigning the array consumer function gsl_spline_init() - it relies on the data passed being a contiguous block of data. This is not the case with you three-level vector - not only it is a cube but also each level has a separate buffer allocated on heap.
This can't be done. Not only with vectors, but even with plain arrays only the last dimension is a contiguous block of data. If gsl_spline_init took an iterator instead of array, you could try to craft some functor to choose appropriate data but I'm not sure it's worth trying. No pointer arithmetic can help you.