Reputation: 105
How can I free up memory in a pointer vector? Here's the code:
class A
{
private:
int x,y,z;
public:
A(param1, param2, param3)
{
x=param1;
y=param2;
z=param3;
}
~A()
{
//prompts an alertbox, warning me about the successful call of the destructor;
}
};
...
vector<A*> list;
list.push_back(new A(1,2,3));
list.erase(list.begin()+index);//SHOULD delete the object from the memory;
list.clear();
I found out that .erase()
doesn't free up memory, neither calls the destructor; I tried to use delete
on every list entry with an iteration, but crashes after one iteration. Already checked if the list entry was already NULL, to avoid any error.
Am I missing something?
Also, I must use only STL, don't need Boost.
Upvotes: 5
Views: 3714
Reputation: 14327
for( std::vector<A*>::iterator i = list.begin(), endI = list.end(); i != endI; ++i)
{
delete *i;
}
list.clear();
or, using new lambda functions
std::for_each( list.begin(), list.end(), []( A* element) { delete element; });
list.clear();
Upvotes: 4
Reputation: 224209
Upon destruction, an STL container will destroy the objects it contains. If those objects are pointers, then it will destroy the pointers. For naked, dumb pointers, this will not delete the objects they point to. That's why it is usually best to use smart pointers for that. Smart pointers will delete the objects they refer to upon deletion; std::shared_ptr
keeps track of copying pointers and how many references to a given object exist, and will only delete the object when the last pointer dies. This is always a good first candidate when looking for a suiting smart pointer. Your container would then be declared like this: std::vector< std::shared_ptr<A> >
However, your compiler/std lib might not come with std::shared_ptr
, which is a feature of the next C++ standard, generally expected next year. It might, however, come with std::tr1::shared_ptr
, which is a TR1 feature from 2003. (If all else fails, boost has boost_shared_ptr
, but you already ruled out boost.)
You can manually manage dynamically allocated objects in STL containers, but it's a burden and prone to errors. For example, you must prevent functions from returning early (before the manual cleanup) through return
statements or exceptions, and you must watch out for copy operations on containers. (Otherwise two containers would have pointers referring to the same objects, which you might then try to destroy twice.)
Manually managing resources is a PITA, prone to errors, and best avoided.
Upvotes: 2
Reputation:
The code you have posted is not legitimate C++. Plus, erase does not delete objects you have allocated, it only erases contents of the vector, which in your case are pointers. The actual objects that you have allocated are not being deleted. Here is a correct way of doing what you want:
#include <vector>
#include <algorithm>
class A
{
int x,y,z;
public:
A (int param1, int param2, int param3) :
x (param1), y (param2), z (param3)
{
}
};
struct Deleter
{
template <typename T>
void operator () (T *obj) const
{
delete obj;
}
};
int
main ()
{
std::vector<A*> list;
list.push_back (new A (1, 2, 3));
list.push_back (new A (4, 5, 6));
list.push_back (new A (7, 8, 9));
std::for_each (list.begin (), list.end (), Deleter ());
list.clear ();
}
You may also look at Boost Ptr Container library that solves this problem in a safe and reusable manner. In C++0x, there is a std::unique_ptr template class that supports movable semantics and can be used with STL containers and algorithms to clean up memory automatically.
Upvotes: 1
Reputation: 490808
erase
only erases what's in the vector (the pointers) without doing anything about what they might point at.
If you want what the point at deleted, you need to handle that yourself.
My advice would be to avoid handling any of this yourself, and consider using Boost ptr_vector
instead.
Upvotes: 3
Reputation: 272822
list.erase
will deallocate the memory for its member elements (and call their destructors, if they exist); it will not call delete
on them.
A Boost shared_ptr
would be the obvious way of doing this. If you don't want to use that, you're either going to write your own smart-pointer class, or iterate through list
and call delete
on each pointer before calling erase
. You can do this neatly with something like:
void my_delete(A *p)
{
delete p;
}
...
std::for_each(list.begin(), list.end(), my_delete);
Upvotes: 8
Reputation: 43331
for(size_t i = 0; i < list.size(); ++i) { delete list[i]; } list.clear();
If your make something like this and your code crashes, post exact code and crash information.
Upvotes: 0