views:

933

answers:

4

Having a vector containing pointers to objects then using the clear function doesn't call the destructors for the objects in the vector. I made a function to do this manually but I don't know how to make this a generic function for any kind of objects that might be in the vector.

void buttonVectorCleanup(vector<Button *> dVector){
    Button* tmpClass;
    for(int i = 0; i < (int)dVector.size(); i++){
     tmpClass = dVector[i];

     delete tmpClass;
    }
}

This is the function I have that works fine for a specific type of object in the vector but I'd like a single function that could take any kind of vector with object pointers.

+6  A: 

The best thing to do is use smart pointers, such as from Boost. Then the objects will be deleted automatically.

Or you can make a template function

template <class T>
void vectorCleanup(vector<T *>& dVector){
    T* tmpClass;
    for(vector<T*>::size_type i = 0; i < dVector.size(); i++){
        tmpClass = dVector[i];

        delete tmpClass;
    }

}

KeithB
What I wanted; though it took me a bit of extra work to get it all working though; see: http://www.codeguru.com/forum/showthread.php?t=250284
DShook
This is the WRONG way to do it. Its not exception safe. You have to explicitly call this to make sure the vector is correctly cleaned up.
Martin York
Couple of other things. Pass by reference (you are making a copy of the vector). The vector is still full of pointers (now all invalid). size() does not return 'unsigned'
Martin York
You are right abut passing a reference. size() returns an unsigned integral type, which is probably usigned, but I changed it to correctly use size_type. I was trying to get rid of the unnecessary cast in the original.
KeithB
Keith: • Why don't you pass a `const` reference? • Why do you use explicit indices instead of iterators? • Why the (completely useless and confusing) temporary variable `tmpClass`? • Why is the container type not a type argument (i.e. why support only `vector`s)?
Konrad Rudolph
If I was doing it for myself, I wouldn't use this approach at all, I would use either smart pointers, or one of the boost pointer containers. In this example, I was trying to keep it as close to the poster's original code as possible.
KeithB
+2  A: 

A couple of other points - you probably want to pass a reference to the vector, not a copy. tmpClass is not needed - you can delete the pointer directly. You should either resize the vector to 0 or replace the pointers with NULL after deleting - otherwise you could access unallocated memory in the calling function.

+8  A: 

You might want to use boost's pointer containers. They are highly efficient and safe.

Leon Timmermans
+2  A: 

I use a special functor to delete the pointer and set it to NULL:

struct delete_ptr
{
    template <typename T>
    void operator()(T& p)
    {
        delete p;
        p = 0;
    }
};

Which is used with std::for_each (also don't forget to #include <algorithm>):

int wmain(int, wchar_t*[])
{
    std::vector<int*> items;
    items.push_back(new int(1));
    items.push_back(new int(2));
    items.push_back(new int(3));
    std::for_each(items.begin(), items.end(), delete_ptr());
};
Johann Gerell
You might want to name this delete_and_zero. The zeroing is rather useless if you're going to clear() the vector<T*> anyway.
MSalters