Vector and queue of pointers data exchange: deep and shallow copies - c++

In my code I have a vector of pointers to objects of SomeClass and a (custom comparison) vector-based priority queue that contains pointers to objects of SomeClass:
std::vector<SomeClass*> my_vector;
std::priority_queue<SomeClass*, vector<SomeClass*>, CustomCompare> my_queue;
Initially my_vector is empty and my_queue is full. Gradually my_queue is emptied into my_vector like this:
my_vector.push_back(my_queue.top());
my_queue.pop();
My question is: Will my_queue.pop() delete the memory that was allocated to the SomeClass object that was pushed back to my_vector therefore causing the element of my_vector to be a dangling pointer? Or otherwise, does the vector make a deep or a shallow copy of the object pointed to by the pointer returned by my_queue.top()?

No deletions will be made. The only thing being copied/removed/pushed_back are pointers. The objects these point to remain alive, provided they have been dynamically allocated. In that case, you will have to do the clean-up yourself.
Depending on the behaviour desired, you may want to use smart poitners to avoid manual memory management, store SomeClass objects instead of pointers, or leave things as they are and make sure to make a cleanup at the end. Bear in mind that it can be difficult to guarantee that your program will safely get to the point where the memory is released, which is one reason smart pointers are preferred over raw pointers to dynamically allocated objects.

my_queue.pop() will only delete the object stored in the queue; in this case, the pointer itself, not the object pointed by the pointer. So you are fine here.
Mandatory remark: consider using smart pointers instead of raw pointers.

Both the queue and the vector only contain pointers. Unless you use smart pointers or shared pointers neither the destructor of the queue nor that of the vector will free the memory.

No. Since they store pointers, they will copy and destroy pointers (which is a no-op). There's no magic involved. If they never store a pointer to the same object simultaneously you may want to make then store unique_ptrs if you want them to destroy the objects in the end. Alternatively you can store the actual objects in a third vector (vector<SomeClass>), and maintain the vector and queue of pointers separately.

You're storing pointer to SomeClass object everywhere, so no my_queue.pop() just removes the pointer from queue and your object is ok, and you will store a copy of pointer to vector, not a deep copy.

Related

C++: Does vector of pointer elements automatically deallocate dynamic memory pointed by each pointer upon destruction?

The title is self explanatory - does the standard vector implementation take care of deallocating dynamic memory pointed to by all the pointers that are in the vector?
No. When you destroy a std::vector it destroys all its elements (calls their destructor) and then deallocates the storage used by the objects. But a (raw) pointer does not have a destructor - destroying it does not deallocate the object it points to - it just destroys the storage used to hold the pointer itself.
If you had had a vector of smart pointers (std::unique_ptr or std::shared_ptr) then it would be a different matter. Those classes do have destructors and do deallocate what they point to upon destruction (unique_ptr always, shared_ptr if it's the last object pointing to the contained object, otherwise it just decrements its reference count).
Note: a std::unique_ptr is a very thin wrapper around a raw pointer, that is designed to optimize away completely. So, using it should have zero overhead over a raw pointer when optimization is enabled. So it'll give you the semantics you want with no overhead compared to doing the manual memory management - manually.
No it doesn't.
If you want "self-deleting" pointers use smart pointers (std::unique_ptr or std::shared_ptr) or (depending on what the pointers are used for) a container such as std::vector, std::array or std::string.
No it doesn't. Containers are not reponsible of the memory management of raw pointers. It would be possible to automatically deallocate your pointer elements if they were smart pointers (RAII : https://fr.wikipedia.org/wiki/Resource_acquisition_is_initialization)
You can see a pointer as a simple integer. Its value represents a memory address. When the vector pointer element is deleted, the bytes allocated to store this address are freed. Thus, the memory address pointed by the pointer is lost (No more reference to it = memory leak).
Containers will never manipulate your instances (Free pointers, modify content). It can only call constructors (Specified one, copy, move...) and the destructor.
Depends on the what pointers the vector is containing, for raw pointers like
std::vector<Something*>
no, you have to do the cleanup yourself.
If the vector contains smart pointers, on the other hand, like std::unique_ptr
std::vector<std::unique_ptr<Something>>
then the cleanup is taken care of for you.
Long story short: try to use smart pointers.

Is it OK to use the addresses of std::vector elements as pointers?

Consider the situation where there is some std::vector<ClassA> and then there are objects of another class that contain pointers to elements of this vector, e.g.:
ClassB Object(&ClassA[12]);
Is this a mine field, in case the vector gets resized, etc.? Should I have an std::vector<ClassA *> instead?
If the vector is resized (e.g. if a push_back() exceeeds vector's current capacity, so there is a need to allocate a bigger chunk of heap memory), then the addresses of vector elements change (so, extern pointers to vector's elements are invalidated).
If you store pointers to ClassA inside the vector, instead of direct instances of ClassA, then the pointers are still valid after vector resize.
However, note that storing owning raw pointers in a std::vector is a very bad thing, and source of leaks.
You should store owning smart pointers, e.g. std::unique_ptr (for unique ownership semantics) or std::shared_ptr (for shared ownership semantics).
For example, you can have a vector<unique_ptr<ClassA>> (so, the vector owns the dynamically allocated instances of ClassA), and you can have raw observing pointers (e.g. simple ClassA*) from an external object.
It is safe, as long as you are not storing that address for later usage (where something that causes the vector to resize or otherwise move the memory would leave you with a dangling pointer).
If you intend to hold onto that pointer, it would be better to have a vector of pointers (or a vector of smart pointers) instead:
std::vector<std::shared_ptr<ClassA>> myVector;

Difference between vector insert and assign

I read that the assign method clears the vector target indexes before assigning anything to it.Does that mean if we have a vector such as:
vector<foo*> somevector;
then the assign method would actually delete foo* before copying data to the target indexes.
then the assign method would actually delete foo* before copying data to the target indexes.
No, it will only delete pointer itself but will not delete objects which pointers pointing to.
You need to be careful when you use raw pointers in STL container. If you dynamically allocates elements in somevector, you endup leaking memory.
More practice way is to use smart pointers in STL container, dynamically allocated memory will be de-allocated in below case:
std::vector<std::unique_ptr<foo>> somevector;
No. std::vector will never call delete on stored pointers. It will simply destroy the object. In the case of a class objects with non-trivial destructors, destroying consists of calling that destructor. In the case of pointers, or any other trivially destructible object, destroying consists of doing nothing.
No, standard containers containing pointers to objects don't ever call delete on the pointers - you are responsible for doing this if/when necessary. This is why storing pointers is a bad idea.

vector of pointer

I just wonder what's wrong with vector of pointer. some of my friend recommend me to use list instead of vector. will this cause a problem:
vector<Fruit*> basket;
basket.push_back(new Apple());
basket.push_back(new Orange());
vector<Fruit*> temp;
temp.push_back(basket[1]);
If I delete vector temp, do I destroy the basket[1] object too? if not, what's the problem with using vector of pointer?
If I delete vector temp, do I destroy the basket[1] object too?
No. First of all, you cannot delete temp; rather, it will get destroyed when going out of scope. And when this happens, the objects pointed by elements of the vector won't be automatically deleted.
This is, however, not a specific problem of vector: using list will not save you from this issue. The problem is rather with raw pointers. If you want the pointed objects to be automatically deallocated when the the lifetime of the last pointer which points to it ends, you should use smart pointers.
Depending on the ownership policy that your application needs, you might choose between shared_ptr and unique_ptr. The caveat with shared_ptr is that referencing cycles shall be avoided, to prevent mutually referencing objects from keeping each other alive. You may want to check weak_ptr in this respect.
Finally, unless you have a good reason for not using vector, vector should be the default choice for a container. From Paragraph 23.2.3/2 of the C++11 Standard:
The sequence containers offer the programmer different complexity trade-offs and should be used accordingly. vector or array is the type of sequence container that should be used by default. list or forward_list should be used when there are frequent insertions and deletions from the middle of the sequence. deque is the data structure of choice when most insertions and deletions take place at the beginning or at the end of the sequence.
If either of the vectors, basket or temp, are destroyed none of the Fruits are destroyed. Anything that is dynamically allocated with new must be deleted. When the vectors go out of scope, they do not delete the objects that are pointed to by their elements. If you delete an object through one vector that is pointed to in the other vector, both point at the now deleted object.
Since your vectors have automatic storage duration, you definitely must not do delete basket; or delete temp;.
It's not recommended to use raw pointers in general, especially with dynamically allocated storage that you may forget to delete. In this case, however, you do need polymorphic behaviour, which is provided by pointers. You should use a smart pointer to avoid the problems with raw pointers. Try a std::vector<std::shared_ptr<Fruit>>.

using C++ vector as a buffer

I am using vector as a buffer to store some objects to be later appended to another vector.
std::vector<Link*> buffer_vector;
std::vector<Link*> main_vector;
main_vector.insert(main_vector.end(),buffer_vector.begin(),buffer_vector.end());
The process of filling the buffer and appending occurs repeatedly. Therefore I need to clear the buffer at every iteration. My concern is if I use .erase or .clear methods to clear the buffer, the objects in the main vector will be deleted. Is this assumption correct?
If yes, is there a workaround for that?
Thank you
vahid
Your concern is incorrect.
main_vector.insert(main_vector.end(),buffer_vector.begin(),buffer_vector.end()); copies the elements from buffer_vector into main_vector.
These copied elements are totally separate from the original elements, and so they are not affected by modifications to the elements that they were copied from.
If you mean clearing the buffer_vector will clear the contents in main_vector, no they are separate copies.
Insertion into a vector is done by copy. In other words, you're pushing a copy of the element into the new vector. A different copy will be deleted when the buffer vector is cleared.
(This assumes that you're pushing the same type into both vectors, and not something like a pointer to an element to a vector in the first vector into the second vector.)
You are copying the elements into the vector, and they will stay there until you delete them.
In the code you show, you are storing pointers into objects. The pointers will be copied, and nothing will happen to the allocated memory when the original vector is cleared or the elements erased.
Actually nothing will happen to the pointed memory when the second vector goes out of scope!! Your program leaks memory, you need to manually manage the pointers or else choose an appropriate smart pointer that you can use inside a vector (consider std::unique_ptr or std::shared_ptr from C++11 or the equivalents from boost or TR1).
You may be confused about how a vector manages its objects. When you push_back into a vector, you make a copy. When you push_back a pointer, it copies the pointer. When you call clear() or erase() it deletes the pointer but not the object the pointer points to.
I am assuming you new'ed all your Link objects and added them to the vector container. You will need to delete them yourself, the container will not destroy the pointed to object for you (even if the container itself is destroyed when it goes out of scope). If you clear() both your containers before calling delete on all your Link objects, you will cause a memory leak (assuming you are not keeping pointers to Link objects somewhere else).