Vector <X *> vec vs vector <X> * vec
What is the difference in memory usage between:
std::vector<X*> vec where each element is on the heap, but the vector itself is not
and
std::vector<X>* vec where is the vector declared on the heap, but each element (on the stack?).
The second option does not make much sense - does this mean that the vector pointer is on the heap, but it points to every element that is on the stack?
std::vector<X*> vec It is an array of class X pointers. This is useful, for example, when creating an array of non-copied classes / objects of type std :: fstream in C ++ 98. So
std::vector<std::fstream> vec; WRONG, and will not work. But
std::vector<std::fstream*> vec; works, while you need to create a new object for each element, for example, if you want 5 Fstream elements you would need to write something like
vec.resize(5); for(unsigned long i = 0; i < vec.size(); i++) { vec[i] = new std::fstream; } Of course, there are many other uses depending on your application.
Now the second case is a pointer to the vector itself. So:
vector<int>* vec; - it's just a pointer! it does not carry any information, and you cannot use it unless you create an object for the vector itself, for example
vec = new vector<int>(); and in the end you can use it like:
vec->resize(5); Now this is not very useful, since vectors in any case store their data on the heap and manage the memory that they carry. Therefore, use it only if you have every reason for this, and sometimes you need it. I have no example of how this might be useful.
The difference is where (and what) you need to do for manual memory management.
Whenever you have a raw C style pointer in C ++, you need to do manual memory management - a raw pointer can point to anything, and the compiler will not do any automatic construction or destruction for you. Thus, you need to know where the pointer points and who owns the memory specified in the rest of your code.
So when you
std::vector<X*> vec; you donโt need to worry about memory management for the vector itself (the compiler will do it for you), but you need to worry about managing memory pointers in X objects for pointers that you specified in the vector. If you select them with new , you need to specify them manually at any time.
If you
std::vector<X> *vec; You need to worry about memory management for the vector itself, but you don't need to worry about memory management for individual elements.
The easiest way is if you have:
std::vector<X> vec; then you donโt have to worry about memory management at all - the compiler will take care of this for you.
In code using a good modern C ++ style, none of the above is true.
std::vector<X*> is a collection of object descriptors of type X or any of its subclasses that you are not. The owner knows how they were allocated, and will free them - you do not know and do not care.
std::vector<X>* in practice will be used only as an argument to a function, which is a vector that you do not own (the caller), but which you are going to change. According to one general approach, the fact that it is a pointer, not a vector, means that it is optional. More rarely, it can be used as a member of a class where it is known that the lifetime of the attached vector is experienced by the class that points to it.
std::vector<std::unique_ptr<X>> is a polymorphic collection of mixed objects of various subclasses of X (and, possibly, X ). Sometimes you can use it non-polymorphically if X expensive to carry, but the modern style makes most types cheap to move around.
Prior to C ++ 11, std::vector<some_smart_pointer<X> > (yes, there is a space between the closing brackets) will be used for both the polymorphic case and the non-copyable case. Note that some_smart_pointer not a std::unique_ptr that does not yet exist, and not a std::auto_ptr that cannot be used in collections. boost::unique_ptr was a good choice. With C ++ 11, the skew requirement for collection elements is weakened to the ability to move, so this reason has completely disappeared. (Some types remain that cannot be copied or moved, such as the ScopeGuard template, but they should not be stored in the collection anyway)