Will stl container free memory after deleting heap based object? - c++

I am fairly new to C++, so I have got this question:
I am know that stl containers do not deallocate memory from heap pointers, one need to deallocate it himself, and I know that containers call destructors of objects being deleted, but say we have this abstract code:
Object* pObject = new Object();
vector<Object>[i] = *pObject;
Now after vector gets destroyed will it actually free memory pObject pointing to? Or it will just call the destructor of Object, making it invalid and leaving the memory marked as "occupied" for memory manager?
Thank you.

You're not actually placing pObject in the std::vector, you're placing a copy of what pObject points to. Therefore the object in the std::vector and *pObject will be totally distinct.
When the std::vector is destroyed, it will call the destructor of this copy of the object, but your original object will be unaffected. I.e. pObject will still point to a valid object, and will have to be delete'd separately.

You have a vector<Object> hence, a vector of Object not Object*. The new is not needed at all in this case.
Standard containers will manage the memory they allocate, not yours. If you have a container of pointers to objects you have newed, then you will need to delete them before the container goes out of scope.
If you want the container (with some allies) to manage the memory for you, use std::shared_ptr or std::unique_ptr. There are boost and tr1 equivalents if you compiler does not yet support C++11.
std::vector<std::shared_ptr<Object>> container;
The container will manage the smart pointers, and the smart pointers in turn manage the memory.

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.

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 pointers, elements of which initialized with new: what happens when assigning a new value?

I have a vector of pointers like this:
std::vector<foo*> stuff;
I initialize each element with a new foo();:
My question is what happens when I reassign one of the vector's elements, say
stuff[3] = new foo();
Am I leaking memory and should I have called delete[] before this? Is this a case where I should be using smart pointers? (never have so far)
Normally I would not be using new but I 'm learning Qt and this is how it seems done in the examples. Qt seems to have smart pointers of its own; should I be using one of those?
Thanks.
yes, you leak when stuff get destructed leaving all those dynamic allocated foo undeleted and unreachable unless you iterate through the vector and call delete.
typically when you want a vector of pointer you use std::shared_ptr
std::vector<std::shared_ptr<foo>> stuff;
stuff[3] = std::make_shared<foo>();
this could potentially be a performance bottleneck if the vector is huge and you try to copy it( then perhaps you want to wrap it in another shared_ptr ), but if you are only accessing the element of the vector it eliminate all the problems about who delete what and when that come with the raw pointer approach.
My question is what happens when I reassign one of the vector's elements, say
stuff[3] = new foo();
Am I leaking memory
Yes, you're leaking memory. The vector doesn't know who's responsible for owning the object you allocated. It's can't tell the difference between:
stuff[3] = new foo();
and
foo f;
stuff[3] = &f;
Therefore it will not any cleanup for you.
and should I have called delete[] before this?
Not quite. delete[] is used to destroy a dynamically allocated array; it's what you would use to destroy something allocated via new[]. To destroy something allocated via plain new, you should use plain delete.
Is this a case where I should be using smart pointers? (never have so far)
Yes. If you used std::shared_ptr<foo> (or boost::shared_ptr<foo> if you can't use C++11), then the std::shared_ptr object would take responsibility for deleteing the object for you.
I don't see any relation with Qt in your code. memory leak occurs when don't call delete after you allocated the object with new. what you should do it to run a loop on that vector and call delete on each item.
a vector makes a copy of the object and stores the copy. Now in your example, the vector is of the type foo*. So when it is passed a pointer to foo, vector makes a copy of the pointer, not the foo itself. Now when you reassign and do other stuff, the copy of the pointer is freed by vector, but not the memory pointed by the pointer. Imagine you have a vector of keys, so the vector makes a copy of key passed to it, and frees the copy of the key. But it never touches the lock for which the key is. That you need to handle yourself. You can get the value and free the element yourself before reassigning.
If foo are QObjects then assign to each a parent (which will be responsible for deleting them - although they could be deleted manually too). And in that case, do not use smart pointers as that will create ownership conflicts.

Vector and queue of pointers data exchange: deep and shallow copies

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.

Will the smart pointer or scoped pointers delete an object when the class has no destructor

Will the smart pointer or scoped pointers delete an object when the class has no destructor
If not, why not just leave the scope and let the object be deleted by itself?
All class members are deleted even if you don't have a destructor when the instance is deleted. Memory leaks occur when you deal with pointers:
class A
{
private:
B* b;
};
In this case, b itself will be destroyed when the instance of A is deleted, but the memory it points to will not.
class A
{
private:
SmartPtr<B> b;
};
In the case of smart pointers, which usually have some reference counting and memory cleanup in the destructor, the memory it points to will be explicitly destroyed by its destructor, and the destructor of the smart pointer will be implicitly called when the instance of the containing class is destroyed.
yes. that s what smart pointers are used for.
http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/smart_ptr.htm
http://en.wikipedia.org/wiki/Smart_pointer
What is a smart pointer and when should I use one?
Yes, smart pointer deletes the object irrespective of whether class has destructor or not. Note that smart pointers are used with objects allocated on heap (using new) and these object won't release memory when they go out of scope, you need to explicitly delete them. Smart pointers will remove this process of explicitly deleting them.
The pointer to the object itself will be deleted. However if there is any dynamically allocated data in the class it will not get freed. The idea of having a destructor is to be able to post-process the class object and mainly - free any resources taken.
new and delete do two things.
new allocates memory and gets an object to construct itself in that memory space.
delete first gets the object to destruct itself then releases the memory.
Note that some smart pointers can be given a custom deleter which doesn't call delete on the object but whatever you ask it to do. There may be occasions when you wish to pass it a no-op.
Your point is well taken; there aren't that many uses for smart pointers
in C++, since most of the time where they might be relevant, you'd be
better off using value semantics, and copying. In the case of
scoped_ptr, the most frequent use is when the actual object is
polymorphic:
scoped_ptr<Base> pObj = condition
? static_cast<Base*>( new Derived1 )
: static_cast<Base*>( new Derived2 );
(Regretfully, at least one of the static_cast is necessary.)
If you are dealing with a container of polymorphic objects, you'll need
shared_ptr instead, and if you're returning a polymorphic object, or
otherwise passing it around, you will use unique_ptr if you can
guarantee its availability, and auto_ptr otherwise—in some cases
where you're passing it around, shared_ptr might be more appropriate.
In the case of returning an object or passing it around, the cost of
copying it might also be a motive for using a smart pointer, even if the
object isn't polymorphic. In such cases, I'd still use value semantics
(i.e. copying and assigning the object itself) unless I had a
performance problem.
Note that smart pointers aren't only used for memory management. I
regularly use auto_ptr in the interface of queues between threads:
once the object has been inserted into the queue, it no longer belongs
to the sending thread; auto_ptr expresses these semantics exactly,
with the auto_ptr in the sending thread becoming invalid. Or a
modifiable singleton (something which should be very, very rare) might
acquire a lock in its instance function, and return a shared_ptr
which frees the lock in its final destructor. I've also used smart
pointers in one or two cases to ensure transactional semantics: in one
case, for example, the objects were in a number of different sets (which
held pointers to them, of course), ordered according to different
criteria. To modify an object, you acquired a shared pointer to it; the
function which returned this shared pointer also removed the objects
from the sets, so that you could safely modify the key values as well,
and the final destructor reinserted them into the sets according to the
new keys. And so on—there are any number of uses for smart
pointers that have nothing to do with memory management or object
lifetime.