This question already has answers here:
C++ How to dynamically create a 2D vector
(3 answers)
Closed 3 years ago.
EDIT:
Strictly speaking it's not a duplicate of the other question, but the accepted answer there can be used to solve my problem.
I would like to use an array that has length specified by a variable n, but once it is created, the length will never change.
In other words, something like
cin >> n;
int* a = new int[n];
is exactly what I want. But using new is a bit inconvenient, for mainly two reasons:
I have to remember to delete[] it in the end, possible leak of memory and the code gets longer;
When it comes to multidimensional arrays, the new process becomes rather complicated. For two dimensional, it will look like
cin >> m >> n;
int** a = new int[m];
for (int i = 0; i < m; i++)
a[i] = new int[n];
and even worse in higher dimensions.
I am aware that there is std::vector which can handle the first issue, but I think I still have to manually adjust the sizes of the vectors when creating multidimensional arrays. It also looks like an overkill, since I don't need to adjust the length after creation.
Also, I tried std::array and found that it doesn't accept variable lengths.
What I want is probably a hybrid, something like myarray<class T, size_t N> which allocates memory dynamically but only once. I can then use myarray<myarray<T, m>, n> to create multidimensional array.
So is there a good solution to this? Preferably I don't want to use a self-written wrapper template, but if there are no better solution then it's still acceptable.
vector<vector<unsigned>> myvec(depth, vector<unsigned>(depth, initialValue));
This will create a 2 dimensional vector of size depth*depth with the initial value initialValue
Related
This question already has answers here:
How do I declare a 2d array in C++ using new?
(29 answers)
Closed 7 years ago.
How do I define a dynamic multi-dimensional array in C++? For example, two-dimensional array? I tried using a pointer to pointer, but somehow it is failing.
The first thing one should realize that there is no multi-dimensional array support in C++, either as a language feature or standard library. So anything we can do within that is some emulation of it. How can we emulate, say, 2-dimensional array of integers? Here are different options, from the least suitable to the most suitable.
Improper attempt #1. Use pointer to pointer
If an array is emulated with pointer to the type, surely two-dimensional array should be emulated with a pointer to pointer to the type? Something like this?
int** dd_array = new int[x][y];
That's a compiler error right away. There is no new [][] operator, so compiler gladly refuses. Alright, how about that?
int** dd_array = new int*[x];
dd_array[0][0] = 42;
That compiles. When being executed, it crashes with unpleasant messages. Something went wrong, but what? Of course! We did allocate the memory for the first pointer - it now points to a memory block which holds x pointers to int. But we never initialized those pointers! Let's try it again.
int** dd_array = new int*[x];
for (std::size_t i = 0; i < x; ++i)
dd_array[i] = new int[y];
dd_array[0][0] = 42;
That doesn't give any compilation errors, and program doesn't crash when being executed. Mission accomplished? Not so fast. Remember, every time we did call a new, we must call a delete. So, here you go:
for (std::size_t i = 0; i < x; ++i)
delete dd_array[i];
delete dd_array;
Now, that's just terrible. Syntax is ugly, and manual management of all those pointers... Nah. Let's drop it all over and do something better.
Less improper attempt #2. Use std::vector of std::vector
Ok. We know that in C++ we should not really use manual memory management, and there is a handy std::vector lying around here. So, may be we can do this?
std::vector<std::vector<int> > dd_array;
That's not enough, obviously - we never specified the size of those arrays. So, we need something like that:
std::vector<std::vector<int> > dd_array(x);
for(auto&& inner : dd_array)
inner.resize(y);
dd_array[0][0] = 42;
So, is it good now? Not so much. Firstly, we still have this loop, and it is a sore to the eye. What is even more important, we are seriously hurting performance of our application. Since each individual inner vector is independently allocated, a loop like this:
int sum = 0;
for (auto&& inner : dd_array)
for (auto&& data : inner)
sum += data;
will cause iteration over many independently allocated inner vectors. And since CPU will only cache continuous memory, those small independent vectors cann't be cached altogether. It hurts performance when you can't cache!
So, how do we do it right?
Proper attempt #3 - single-dimensional!
We simply don't! When situation calls for 2-dimensional vector, we just programmatically use single-dimensional vector and access it's elements with offsets! This is how we do it:
vector<int> dd_array(x * y);
dd_array[k * x + j] = 42; // equilavent of 2d dd_array[k][j]
This gives us wonderful syntax, performance and all the glory. To make our life slightly better, we can even build an adaptor on top of a single-dimensional vector - but that's left for the homework.
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().
int * a;
a = new int[10];
cout << sizeof(a)/sizeof(int);
if i would use a normal array the answer would be 10,
alas, the lucky number printed was 1, because sizeof(int) is 4 and iszeof(*int) is 4 too. How do i owercome this? In my case keeping size in memory is a complicated option. How do i get size using code?
My best guess would be to iterate through an array and search for it's end, and the end is 0, right? Any suggestions?
--edit
well, what i fear about vectors is that it will reallocate while pushing back, well you got the point, i can jus allocate the memory. Hoever i cant change the stucture, the whole code is releevant. Thanks for the answers, i see there's no way around, so ill just look for a way to store the size in memory.
what i asked whas not what kind of structure to use.
Simple.
Use std::vector<int> Or std::array<int, N> (where N is a compile-time constant).
If you know the size of your array at compile time, and it doens't need to grow at runtime, then use std::array. Else use std::vector.
These are called sequence-container classes which define a member function called size() which returns the number of elements in the container. You can use that whenever you need to know the size. :-)
Read the documentation:
std::array with example
std::vector with example
When you use std::vector, you should consider using reserve() if you've some vague idea of the number of elements the container is going to hold. That will give you performance benefit.
If you worry about performance of std::vector vs raw-arrays, then read the accepted answer here:
Is std::vector so much slower than plain arrays?
It explains why the code in the question is slow, which has nothing to do with std::vector itself, rather its incorrect usage.
If you cannot use either of them, and are forced to use int*, then I would suggest these two alternatives. Choose whatever suits your need.
struct array
{
int *elements; //elements
size_t size; //number of elements
};
That is self-explanatory.
The second one is this: allocate memory for one more element and store the size in the first element as:
int N = howManyElements();
int *array = int new[N+1]; //allocate memory for size storage also!
array[0] = N; //store N in the first element!
//your code : iterate i=1 to i<=N
//must delete it once done
delete []array;
sizeof(a) is going to be the size of the pointer, not the size of the allocated array.
There is no way to get the size of the array after you've allocated it. The sizeof operator has to be able to be evaluated at compile time.
How would the compiler know how big the array was in this function?
void foo(int size)
{
int * a;
a = new int[size];
cout << sizeof(a)/sizeof(int);
delete[] a;
}
It couldn't. So it's not possible for the sizeof operator to return the size of an allocated array. And, in fact, there is no reliable way to get the size of an array you've allocated with new. Let me repeat this there is no reliable way to get the size of an array you've allocated with new. You have to store the size someplace.
Luckily, this problem has already been solved for you, and it's guaranteed to be there in any implementation of C++. If you want a nice array that stores the size along with the array, use ::std::vector. Particularly if you're using new to allocate your array.
#include <vector>
void foo(int size)
{
::std::vector<int> a(size);
cout << a.size();
}
There you go. Notice how you no longer have to remember to delete it. As a further note, using ::std::vector in this way has no performance penalty over using new in the way you were using it.
If you are unable to use std::vector and std::array as you have stated, than your only remaning option is to keep track of the size of the array yourself.
I still suspect that your reasons for avoiding std::vector are misguided. Even for performance monitoring software, intelligent uses of vector are reasonable. If you are concerned about resizing you can preallocate the vector to be reasonably large.
I am trying to learn C++ and trying to write a code for a simple hash table like following structure:
array[0][0] array[0][1] array[0][2]
key 1 value 1 value 2
array[1][0] array[1][1]
key 2 value 3
array[2][0] array[2][1] array[2][2]
key 3 value 4 value 5
means Array of Dynamic Arrays. Now, I can't understand how to define the array like that ?
Any help on this will be grateful.
If you really did need to create a dynamic array of dynamic arrays you would have to do it using the new keyword for both arrays. For example:
// an array of int pointers... each points to the start of an array
int** arrays = new int*[10];
arrays[0] = new int[99]; // populate the first element of the array of arrays
arrays[1] = new int[47]; // arrays don't have to be the same size.
Of course I highly recommend NOT doing this. You have to then remember to use delete[] on each member of arrays and on arrays itself.
Really you should use the built in std::vector type for this. It is why it is there (I voted for the other answers!).
Just as a note, this is not contiguous memory either. Also if you do want the member arrays to be the same size you could allocate their memory in a for loop.
In C++ you would use a std::vector<T> and nest two of them in order to get a 2D array.
std::vector<std::vector<my_type>> vec;
std::vector<my_type> v;
vec.push_back(v);
v.push_back(mytype);
Create a vector <vector <T> >.
For example
vector <vector <string> > array;
vector <string> temp;
temp.push_back(key1);
temp.push_back(value1);
temp.push_back(value2);
array.push_back(temp);
.
.
.
This is old, and I'm sure I'm not writing anything answer posters don't know in the back of their minds, but OP looks like he's doing an assignment for homework. My homework requires me to write out routines with out using any STL resources. In that case the only possible answer here is the first one. Homework in the beginning isn't about efficiency, it's demonstrating use of lesson material.
Unfortunately much of the time what they want you to demonstrate is never illustrated in the lessons.
Which brings OP's like this one to dig the web for hard to find reference. Hard to find because nobody really does it the way they are required to do it.
I followed this link because the title led me to believe I would find resource for a static array of dynamic arrays. So I will post that application incase anyone else is looking for that reference.
int main()
{
int* time[2];
int userInp;
userInp = 5;
time[0] = new int[userInp];
time[0][1] = 6;
cout << time[0][1];
delete time[0];
return 0;
}