Tibor
Tibor

Reputation: 105

How can I free a pointer vector?

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

Answers (6)

Cătălin Pitiș
Cătălin Pitiș

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

sbi
sbi

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

user405725
user405725

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

Jerry Coffin
Jerry Coffin

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

Oliver Charlesworth
Oliver Charlesworth

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

Alex F
Alex F

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

Related Questions