I have a large array of objects (10s Millions) of class A and I want to add a vector as a member to the class A. This vector is needed just for few percent of objects in the array. I was wondering, would it be a wise choice to add a vector to the class? how much memory will take an empty vector?
Now we know that empty vector are not very “big” (VC2012x64 intellisense show sizeof(std::vector<int>) is 16 byte). If sizeof(A) is much bigger than size-of vector adding a vector member to A could be a good solution for you. But if it is not good, and will add to much memory, and really not many A has the vector, I’d create a second container with the vectors. For example:
#include <unordered_map>
unordered_map<size_t , vector<T>> VectorForA;
where size_t is mean to be the type of the index of the big array of A, and vector<T> the type of the vector you want to add to A. This could be good for a fixed index "big" array. If somehow the A's in the big array dont have fixed positions, making the value of A the key could led to a simpler code(also, only if the values of A dont repeat).
NOTE: I was (I'm) wating to see a full answer from #Andy Prowl or #Tony D with I think will be very usefull
Related
I give online coding contests, where the speed of the program is everything. Over the time I have come across 3 ways to use the concept of array in C++. The questions of the contests usually require us to create a dynamic array of the given size. So its just a one time creation of the dynamic array as per the input and we don't resize the array again.
std::vector
Vectors look the most fancy and everyone tends to love them. But few days back one of the question gave me the TIME_LIMIT_EXCEEDED error when doing it with vectors.When I implemented the same logic with normal arrays, the program was submitted successfully.On researching, I found out that using the push_back() function takes a long time as compared to a normal arr[i]=x;
std::array
I don't have much knowledge about its performance. But it looks like a nicer way to handle arrays.
default arrays in C++
I do the dynamic allocation using int *arr=new int[given_size]; and then use the array normally.Passing an array as argument is not as simple as vectors but its not a big deal.
Apart from this there are also times when I have to work with 2D arrays and I am always unsure about what could be the fastest way. vector<vector<int>> is regarded slow in some forums and so is using multidimensional pointers. So I like to use a 1D array with a typedef function to handle its index but it gets complicated when I have to pass a row to a function.
Most of the answers in forums are based on what the OP was trying to do and this gives different answers. What I want to know is which is the best and long term way to use to have maximum speed/efficiency.
push_back takes a long time compared to arr[i]=x;.
Sorry but you are showing your lack of experience with vectors here, because your examples do two different things.
You are comparing something like this code
vector<int> vec; // vector created with size zero
for (...)
vec.push_back(x); // vector size increases
with this code
int arr[N];
for (...)
arr[i] = x;
The difference is that in the first case the vector has size 0 and it's size increases as you add items to it (this takes extra time), but in the second case the array starts out at it's final size. With an array this is how it must be, but with vectors you have a choice. If you know what the final size of the vector is you should code it like this
vector<int> vec(N); // vector created at size N, note use () not []
for (...)
vec[i] = x;
That is the code you should be comparing with the array code for efficiency,
You might also want to research the resize and reserve methods of a vector. Vectors (if nothing else) are much more flexible than arrays.
i have a class in which it's protected section i need to declare an array with unknown size (the size is given to the constructor as a parameter), so i looked around and found out that the best possible solution is to declare an array of pointers, each element points to an integer:
int* some_array_;
and simply in the constructor i'll use the "new" operator:
some_array_ = new int[size];
and it worked, my question is: can i declare an array in a class without defining the size? and if yes how do i do it, if not then why does it work for pointers and not for a normal array?
EDIT: i know vecotrs will solve the problem but i can't use them on my HW
You have to think about how this works from the compiler's perspective. A pointer uses a specific amount of space (usually 4 bytes) and you request more space with the new operator. But how much space does an empty array use? It can't be 0 bytes and the compiler has no way of knowing what space to allocate for an array without any elements and therefore it is not allowed.
You could always use a vector. To do this, add this line of code: #include <vector> at the top of your code, and then define the vector as follows:
vector<int> vectorName;
Keep in mind that vectors are not arrays and should not be treated as such. For example, in a loop, you would want to retrieve an element of a vector like this: vectorName.at(index) and not like this: vectorName[index]
Lets say that you have an integer array of size 2. So you have Array[0,1]
Arrays are continuous byte of memery, so if you declare one and then you want to add one or more elements to end of that array, the exact next position (in this case :at index 2(or the 3rd integer) ) has a high chance of being already allocated so in that case you just cant do it. A solution is to create a new array (in this case of 3 elements) , copy the initial array into the new and in the last position add the new integer. Obviously this has a high cost so we dont do it.
A solution to this problem in C++ is Vector and in Java are ArrayLists.
I want a program that creates an undetermined amount of lists. The size of each list is fixed, but I can't determine at compile time how many lists am I going to need.
I understand I cannot create a vector of arrays. I also understand I can use a vector of vectors, but I wonder if this is the best efficient way to do it considering the fact I need to reserve a fixed amount of memory each time I need a new array.
Erm, you can use a vector of arrays, for example,
std::vector<std::array<T, N>> some_vec;
#Nim is right, but I cannot upvote yet :p
Also his solution is C++11.
Another alternative which is to be preferred over std::vector<std::vector<T> > is to have one vector with the dimensions X * Y. Then you can access your elements with v[y * Y + x];
This works with all versions of C++ and should be just as efficient as the std::vector<std::array<T, N> > solution.
I want to allocate memory of 10^9*10^9 in a double dimension array but this is not possible.is their any way out?
I think vector could be solution to this but i dont know how to do it.
You cannot allocate 1018 bytes of memory in any computer today (that's roughly a million terabytes). However, if your data is mostly zeros (ie. is a sparse matrix), then you can use a different kind of data structure to store your data. It all depends on what kind of data you are storing and whether it has any redundant characteristics.
Assuming that the number of non-zero elements is much less than 10^18, you'll want to read up on sparse arrays. In fact, it's not even a requirement that most of the elements in a sparse array be zero -- they just need to be the same. The essential idea is to keep the non-default values in a structure like a list; any values not found in the list are assumed to be the default value.
I want to allocate memory of 10^9*10^9 in a double dimension array but this is not possible.is their any way out?
That's way beyond current hardware capabilities, and array this big is unsuitable for any practical purpose (you're free to calculate how many thousands of years it would take to walk through every element).
You need to create "sparse" array. Store only non-zero elements in memory, provide array-like interface to access them, but internally store them in something like std::map<std::pair<xcoord, ycoord>, value>, return zero for all elements not in map. As long as you don't do something reckless like trying to set every element to non-zero value, this should be sufficient array replacement.
so....
What do you need that much memory for?
I have a class "foo" that has a multi dimensional array and need to provide a copy of the array through a getArray member. Is there a nice way of doing this when the array is dynamically created so I can not pass the array back a const as the array is always being deleted, recreated etc. I thought about creating a new dynamic array to pass it back but is this acceptable as the calling code would need to know to delete this etc.
Return an object, not a naked array. The object can have a copy constructor, destructor etc. which will do the copying, deletion etc. for the user.
class Matrix {
// handle creation and access to your multidim array
// including copying, deletion etc.
};
class A { // your class
Matrix m; // the classes matrix
Matrix getArray() {
return m;
}
};
Easy answer to your question is, not this is not a good design, as it should be the creating class that should handle the deletion/release of the array.
The main point is why do you keep deleting/recreating this multi dimensional array? Can you not create one instance, and then just modify when need be?
Personally I would return the array as it is, and iterate over it and do any calculations/functions on it during the loop therefore saving resources by not creating/deleting the array.
Neil's probably the best answer. The second best will be not to use an array. In C++, when you talk about dynamic array, it means vector.
There are two possibilities:
nested vectors: std::vector<int, std::vector<int> >(10, std::vector<int>(20))
simple vector: std::vector<int>(200)
Both will have 200 items. The first is clearly multi-dimensional, while the second leaves you the task of computing offsets.
The second ask for more work but is more performing memory-wise since a single big chunk is allocated instead of one small chunks pointing to ten medium ones...
But as Neil said, a proper class of your own to define the exact set of operations is better :)