Does myVector.erase(myPtr) delete the object pointed by myPtr? - c++

If I have the following code,
Foo *f = new Foo();
vector<Foo*> vect;
vect.push_back(f);
// do stuff
vect.erase(f);
Did I create a memory leak?
I guess so, but the word erase gives the feeling that it is deleting it.
Writing this, I am wondering if it is not a mistake to put a pointer in a STL vector. What do you think?

Yes, you created a memory leak by that. std::vector and other containers will just remove the pointer, they won't free the memory the pointer points to.
It's not unusual to put a pointer into a standard library container. The problem, however, is that you have to keep track of deleting it when removing it from the container. A better, yet simple, way to do the above, is to use boost::shared_ptr:
{
boost::shared_ptr<foo> f(new foo);
std::vector< boost::shared_ptr<foo> > v;
v.push_back(f);
v.erase(v.begin());
} /* if the last copy of foo goes out of scope, the memory is automatically freed */
The next C++ standard (called C++1x and C++0x commonly) will include std::shared_ptr. There, you will also be able to use std::unique_ptr<T> which is faster, as it doesn't allow copying. Using std::unique_ptr with containers in c++0x is similar to the ptr_container library in boost.

Another option is to use the Boost Pointer Containers. They are designed to do exactly what you want.

Alternatively there is the boost::ptr_vector container.
It knows it is holding pointers that it owns and thus auto deletes them.
As a nice side affect, when accessing elements it returns a reference to the object not the pointer to make the code look nice.
Foo *f = new Foo();
boost::ptr_vector<Foo> vect;
vect.push_back(f);
// do stuff
vect.erase(f);

To clarify why the pointer is not deleted, consider
std::vector<char const*> strings;
strings.push_back("hello");
strings.push_back("world");
// .erase should not call delete, pointers are to literals
std::vector<int*> arrays;
strings.push_back(new int[10]);
strings.push_back(new int[20]);
// .erase should call delete[] instead of delete
std::vector<unsigned char*> raw;
strings.push_back(malloc(1000));
strings.push_back(malloc(2000));
// .erase should call free() instead of delete
In general, vector<T*>::erase cannot guess how you'd dispose of a T*.

It is definitely not a mistake to point a pointer into a standard container (it's a mistake to make a container of auto_ptr's however). Yes, you do need to explicitly delete to free the memory pointed to by the individual elements, or you can use one of the boost smart pointers.

vector deletes the data it contains. Since your vector contains pointers, it only deletes the pointers, not the data they may or may not point to.
It's a pretty general rule in C++ that memory is released where it was allocated. The vector did not allocate whatever your pointers point to, so it must not release it.
You probably shouldn't store pointers in your vector in the first place.
In many cases, you would be better off with something like this:
vector<Foo> vect;
vect.push_back(Foo());
// do stuff
vect.erase(f);
Of course this assumes that Foo is copyable, and that its copy constructor is not too expensive, but it avoids memory leaks, and you don't have to remember to delete the Foo object. Another approach would be to use smart pointers (such as Boost's shared_ptr), but you may not need pointer semantics at all, in which case the simple solution is the best one.

STL containers will not free your memory. The best advice is using smart pointers, knowing that std::auto_ptr will not fit inside containers. I would recommend boost::shared_ptr, or if your compiler vendor has support for TR1 extensions (many do) you can use std::tr1::shared_ptr.
Also note that the vector will not even free the internal memory reserved for the pointer. std::vectors never downsize not even with a call to clear(). If you need to downsize a vector you will have to resort to creating another vector and swapping contents.

Related

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 isn't
and
std::vector<X>* vec
where the vector is declared on the heap, but each element is (on the stack?).
The second option doesn't make much sense- does it mean the vector pointer is on the heap, but it points back at each element, which are on the stack??
std::vector<X*> vec
Is an array of pointers of the class X. This is useful, for example, when making an array of non-copyable classes/objects like std::fstream in C++98. So
std::vector<std::fstream> vec;
is WRONG, and won't work. But
std::vector<std::fstream*> vec;
works, while you have to create a new object for each element, so for example if you want 5 fstream elements you have 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 of the vector itself. So:
vector<int>* vec;
is just a pointer! it doesn't carry any information, and you can't use it unless you create the object for the vector itself, like
vec = new vector<int>();
and eventually you may use it as:
vec->resize(5);
Now this is not really useful, since vectors anyway store their data on the heap and manage the memory they carry. So use it only if you have a good reason to do it, and sometimes you would need it. I don't have any example in mind on how it could be useful.
If this is what you really asked:
vector<X>* vec = new vector<X>();
it means that the whole vector with all its elements is on the heap. The elements occupy a contiguous memory block on the heap.
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 some manual memory management -- the raw pointer can point at anything, and the compiler won't do any automatic construction or destruction for you. So you need to be aware of where the pointer points and who 'owns' the memory pointed at in the rest of your code.
So when you have
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 do need to worry about the memory management of the pointed at X objects for the pointers you put in the vector. If you're allocating them with new, you need to make sure to manually delete them at some point.
When you have
std::vector<X> *vec;
You DO need to worry about memory management for the vector itself, but you DON'T need to worry about memory management for the individual elements.
Simplest is if you have:
std::vector<X> vec;
then you don't need to worry about memory management at all -- the compiler will take care of it for you.
In code using good modern C++ style, none of the above is true.
std::vector<X*> is a collection of handles to objects of type X or any of its subclasses, which you do not own. The owner knows how they were allocated and will deallocate them -- you don't know and don't care.
std::vector<X>* would in practice, only ever be used as a function argument which represents a vector you do not own (the caller does) but which you are going to modify. According to one common approach, the fact that it's a pointer rather than a vector means that it is optional. Much more rarely it might be used as a class member where the lifetime of the attached vector is known to outlive the class pointing to it.
std::vector<std::unique_ptr<X>> is a polymorphic collection of mixed objects of various subclasses of X (and maybe X itself directly). Occasionally you might use it non-polymorphically if X is expensive to move, but modern style makes most types cheap to move.
Prior to C++11, std::vector<some_smart_pointer<X> > (yes, there's a space between the closing brackets) would be used for both the polymorphic case and the non-copyable case. Note that some_smart_pointer isn't std::unique_ptr, which didn't exist yet, not std::auto_ptr, which wasn't usable in collections. boost::unique_ptr was a good choice. With C++11, the copyability requirement for collection elements is relaxed to moveability, so this reason completely went away. (There remain some types which are neither copyable nor moveable, such as the ScopeGuard pattern, but these should not be stored in a collection anyway)

How should I retain a pointer to an std::unique_ptr?

I have a vector:
std::vector<std::unique_ptr<myClass>> vec;
//filling the vector
vec.push_back(std::unique_ptr<myClass>(new myClass()));
vec.push_back(std::unique_ptr<myClass>(new myClass()));
vec.push_back(std::unique_ptr<myClass>(new myClass()));
I need a handle to a specific instance of myClass that doesn't need to worry about ownership, e.g:
std::unique_ptr<myClass>& myInstance;
The problem is that myInstance will need point to different instances of myClass during runtime.
I know I could use an std::shared_ptr, but I want to keep them std::unique_ptr's so if something already initialized is added the ownership is transferred to vec.
How should I retain a pointer to an std::unique_ptr?
Additionally, would it considered bad practice to use a raw pointer here? The pointer won't need to manage any resources, but I don't want my code to get confusing.
The comments to your post indicate that using a raw pointer in a "non-owning" capacity should be OK. I tend to concur with that general sentiment, but your case needs further examination.
For your situation you should not use "a pointer to an std::unique_ptr". The problem is that when you (or a maintenance programmer) adds to the vector, the vector could reallocate. If it does, your pointer is invalidated and must not be used.
One option would be to use the index into the vector instead of a pointer. This has the problem of breaking if you ever delete or rearrange entries in the vector.
Another, more robust, option is to use a pointer direct to the actual myClass object rather than the unique_ptr that owns it. This option is enabled by your use of a vector of unique_ptrs of objects instead of the more usual vector of objects.

Is it safe to push_back 'dynamically allocated object' to vector?

Whenever I need to add dynamically allocated object into a vector I've been doing that the following way:
class Foo { ... };
vector<Foo*> v;
v.push_back(new Foo);
// do stuff with Foo in v
// delete all Foo in v
It just worked and many others seem to do the same thing.
Today, I learned vector::push_back can throw an exception. That means the code above is not exception safe. :-( So I came up with a solution:
class Foo { ... };
vector<Foo*> v;
auto_ptr<Foo> p(new Foo);
v.push_back(p.get());
p.release();
// do stuff with Foo in v
// delete all Foo in v
But the problem is that the new way is verbose, tedious, and I see nobody's doing it. (At least not around me...)
Should I go with the new way?
Or, can I just stick with the old way?
Or, is there a better way of doing it?
If all you care about is exception-safety of this operation:
v.reserve(v.size()+1); // reserve can throw, but that doesn't matter
v.push_back(new Foo); // new can throw, that doesn't matter either.
The issue of a vector having responsibility for freeing the objects pointed to by its contents is a separate thing, I'm sure you'll get plenty of advice about that ;-)
Edit: hmm, I was going to quote the standard, but I actually can't find the necessary guarantee. What I'm looking for is that push_back will not throw unless either (a) it has to reallocate (which we know it won't because of the capacity), or (b) a constructor of T throws (which we know it won't since T is a pointer type). Sounds reasonable, but reasonable != guaranteed.
So, unless there's a beneficial answer over on this question:
Is std::vector::push_back permitted to throw for any reason other than failed reallocation or construction?
this code depends on the implementation not doing anything too "imaginative". Failing that, your solution from the question can be templated up:
template <typename T, typename Container>
void push_back_new(Container &c) {
auto_ptr<T> p(new T);
c.push_back(p.get());
p.release();
}
Usage then isn't too tedious:
struct Bar : Foo { };
vector<Foo*> v;
push_back_new<Foo>(v);
push_back_new<Bar>(v);
If it's really a factory function rather than new then you could modify the template accordingly. Passing a lot of different parameter lists in different situations would be difficult, though.
Your new way is more exception safe but there is a reason that you don't see it done anywhere else.
A vector of pointers only owns the pointers, it doesn't express ownership of the pointed-to objects. You are effectively releasing ownership to an object that doesn't "want" ownership.
Most people will use a vector of shared_ptr to express the ownership correctly or use something like boost::ptr_vector. Either of these mean that you don't have to explicitly delete the objects whose pointers you are storing which is error prone and potentially exception 'dangerous' at other points in the program.
Edit: You still have to be very careful with insertion into ptr_vector. Unfortunately, push_back taking a raw pointer provides the strong guarantee which means that either insertion succeeds or (effectively) nothing happens, so the object passed in is neither taken over nor destroyed. The version taking a smart pointer by value is defined as calling .release() before calling the strongly guaranteed version which effectively means that it can leak.
Using a vector of shared_ptr together with make_shared is much easier to use correctly.
The preferred way to do this is to use a container of smart pointers, for example, a std::vector<std::shared_ptr<Foo> > or a std::vector<std::unique_ptr<Foo> > (shared_ptr can be found in Boost and C++ TR1 as well; std::unique_ptr is effectively restricted to C++0x).
Another option is to use a container that owns dynamic objects, like those containers provided by the Boost Pointer Containers library.
How resilient to memory shortage is your program? If you really care about this you have to be prepared for new to throw as well. If you aren't going to handle that, I would not worry about jumping through the push_back hoops.
In the general case, if you run out of memory, the program already has likely insurmountable problems unless it's specifically designed to run forever in a constrained footprint (embedded systems) - in that case you do have to care about all of these cases.
If that applies to you, you could have a lengthy code review and retest cycle ahead of you. My guess is that you are OK to follow your team's practice here, though.
As others have pointed out, using vector to store raw pointers has its own problems, and there is a wealth of material on this site and in the other answers to direct you to a safer pattern.

Qt and auto_ptr

I just discovered the concept of an auto_ptr and am liking it! As Qt often requires a QList or QVector<(some QObject or QWidget) *>, is there any concrete reason why auto_ptr should be avoided. If I'm right, it allows you to replace this:
std::vector<MyClass*> vec;
/* add several elements to the vector and do stuff with them */
for(size_t i=0; i<vec.length(); ++i)
{
delete vec[i];
}
vec.clear();
with somthing much shorter (ie no cleanup)
std::vector<auto_ptr<MyClass>> vec;
/* add several elements to the vector and do stuff with them */
// no need for the delete loop
...Can Qt still work its shared memory magic with auto_ptr's? Does the parent-child automagic memory management still function transparently? Thanks
Qt has its own smart pointer classes that are in many ways superior to std::auto_ptr, specifically in that some of them can be put into containers with no issues. std::auto_ptr has ownership-transfer copy semantics, and so will not work as expected if you try to put it into a container.
Try using QSharedPointer. It's a reference counted smart pointer that deletes its contained object when there are no more copies of the smart pointer left. Unlike std::auto_ptr there can be multiple copies of the same QSharedPointer at once, and therefore it plays well with containers.
If you want a container that has ownership of pointers then look at boost pointer containers.
You put pointers into the container, but like the other containers they are then treated like normal objects which makes it easier to use them with standard algorithms (i.e. no need to write wrapper classes). When the pointer container goes out of scope it will call delete on all pointers in the container:
boost::ptr_vector<MyClass> v;
v.push_back(new MyClass(12));
std::for_each(v.begin(), v.end(), DoStuff());
// Destroyed here.
std::auto_ptr cannot be used in std::vector, because std::vector expects to be able to copy its contents, and you can't copy a std::auto_ptr in the normal sense. Copying means winding up with two identical things, and if you had two identical std::auto_ptrs what they pointed to would be double-freed when they went out of scope. (What happens instead is that the auto_ptr being copied from has its internal pointer zeroed out, and the one being copied to is now what the old one used to be.)
Use shared_ptr, which is often available as boost::shared_ptr or on Visual C++ std::tr1::shared_ptr, and which will be in the C++0x standard library, or use whatever Qt has. Those can be copied, and therefore can go into containers.

Should I delete vector<string>?

I've painfully learned during last few days a lot about programming in c++.
I love it :)
I know I should release memory - the golden "each malloc=free" or "each new=delete" rules exist now in my world, but I'm using them to rather simple objects.
What about vector ? Wherever I can, I'm using vector.clear() but that clearly isn't enough, because I'm having huge memory leaks.
Could you guide me on how should I treat this thing?
*Edit
Thanks, your comments made me think about the alghorithm of this application and I'll be able to eliminate the vector totally. :O
Sorry - I started explaining what is my use case here and I found out what I really need. It's like that when you code last 3 days for 18 hours a day :|
*Edit 2
This is crazy. By small changes in code, I've eliminated memory usage from 2x130 mb (constantly growing) into 2x 13,5mb, constant size. Thanks for making me think about that in another way.
Btw. such self code review got a name - anyone remember that? It's when you ask anyone (even your mother or dog) and start explaining what's your problem - and suddenly you solve this 5 hour problem yourself, just by trying to look at it from other point of view, or just by trying to summarize what's it all about. I often find myself being catched on that...
The rule is that when you clear a vector of objects, the destructor of each element will be called. On the other hand, if you have a vector of pointers, vector::clear() will not call delete on them, and you have to delete them yourself.
So if all you have is a vector of strings, and not pointers to strings, then your memory leaks must be caused by something else.
You don't need to be doing this. std::string cleans itself up, so the strings are not your problem. Remember that YOU didn't use new so YOU don't have to use delete.
You should probably learn about RAII - it makes allocation and deallocation much simpler. You'll avoid memory leaks this way.
Calling v.clear() will destroy all objects that are currently held inside v, but it will not release the memory (it is assumed that the vector will soon be filled again).
If you really want to free the memory, the idiom is
vector<string>().swap(v);
This will create a new (temporary) vector and swap its contents with v. The temporary vector is then destroyed, freeing the memory along with it.
Deleting elements from STL containers is guaranteed to call destructors on these elements.
However, if you have a container of some pointer-to-T type, then you still have to free the pointed-to memory yourself (in this case, the "destructor" for the pointer gets called, which is a no-operation).
If you do not want to manually manage memory in this case, consider using a smart-pointer solution or a pointer container.
The vector (like all standard containers) owns the objects inside it.
So it is responsible for destroying them.
Note: If you vector contains pointers then it owns the pointers (not what the pointers point at). So these need to be deleted. But there are easier ways.
You could use a vector of smart pointers. In fact you should be using some form of smart pointer for nearly everything. If you are using pointers you are probably still programming like a C programmer.
So:
std::vector<int> data; // clear is fine.
std::vector<int*> data1; // Now things need to be deleted.
// alternative 1:
std::vector<boost::shared_ptr<int> > data2; // The shared pointer will auto
// delete the pointer.
// alternative 2:
boost::ptr_vector<int> data3; // Here the container knows that
// it is holding pointers and will
// auto de-reference them when you
// its members.
But it sounds like you need to start thinking about learning about smart pointers.
int* x = new int(5);
// Do stuff.
*x = 8;
delete x;
// --- Instead use a smart pointer:
std::auto_ptr<int> x(new int(5));
// Do stuff.
*x = 8;
// No delete (the auto ptr handles it.
If you have a vector and it goes out of scope, all objects in the vector are destroyed. There isn't really a need to call clear() unless you want to dump the contents and reuse the vector.
However if you by any chance are using something like a vector then the destructor of the objects being pointed to will not be called as the vector destructor doesn't follow the indirections represented by the pointers.
All that said, have you actually confirmed that you've got genuine memory leaks and that they are caused by the data in the vector?
Give a use case. The destructor on the string is getting called by vector::clear. Your problem lies elsewhere my friend.
also check out:
Does std::vector.clear() do delete (free memory) on each element?
As rlbond suggested, use RAII.
It's a good rule of thumb to never put new and delete calls into your main code flow. Always try to put them into objects so that the object destructor can free what needs to be freed. In this way, you avoid needing to remember to call delete and it makes your code exception safe (assuming that you make your object's operations exception safe).
For example, if you had a vector of pointers to STL strings or C-style character arrays, put that into a StringContainer (use a better name) and have the StringContainer hold a vector and in the StringContainer destructor run a for loop to delete each string in the vector.
You can make the vector inside the StringContainer a public member and mess around with it directly, but it's even better design to make it private or protected and add some member functions to manage the string* vector.
So your main C++ program should never see a new or delete anywhere. Instead it should have a lot of stack allocated objects, auto_ptrs and shared_ptrs.