views:

146

answers:

3

I tried this:

....
vector<players*> player;
for (int i = 0; i<10; i++)
{
    player.push_back(new players());
}
...

And I wonder if I need to free memory for the vector? If so, how?

+2  A: 

since you are creating new players(), you will have to delete them. probably best to iterate through the vector deleting the players and then clean up your vector.

yamspog
+8  A: 

If you need to store pointers to things in a container, you should either store some sort of smart pointer (like std::tr1::shared_ptr or boost::shared_ptr) or use a container designed for storing pointers, like those found in the Boost Pointer Container Library.

If you do store bare pointers, you need to remember to delete the pointers in the container before the container is destroyed. This includes any time that an exception is thrown that might cause the container to be destroyed. Getting this right is tedious, bug-prone, and wholly unnecessary given the facilities mentioned in the previous paragraph.

James McNellis
+1 for ptr_container
vladr
Would be worth mentioning that with `C++0x` come the `unique_ptr` which nicely fit for this kind of task. With a much lower overhead that `shared_ptr`.
Matthieu M.
+4  A: 

Yes, you do need to delete them yourself. The vector is only going to "destruct" the pointers (which does nothing).

If you can, use the Boost pointer containers library, and you won't have to worry about it. However, if you can't you need to wrap the container up. Consider an exception is thrown between the time the container is populated and the time its elements are deleted. You will not execute the element delete code and leak.

A simple wrapper might look like:

struct default_deleter
{
    template <typename T>
    void operator()(T* pPtr)
    {
        delete pPtr;
    }

};

template <typename T, typename Deleter = default_deleter>
struct container_wrapper
{
    typedef T container_type;
    typedef Deleter deleter_type;

    container_wrapper(container_type pContainer = container_type()) :
    container(pContainer)
    {}

    ~container_wrapper(void)
    {
         std::for_each(container.begin(), container.end(), deleter_type());
    }

    container_type container;
};

Use it like:

typedef std::vector<int*> vec_intptr;
typedef container_wrapper<vec_intptr> vec;

vec v;
v.container.push_back(new int); // and never worry about it again

This is a simple wrapper. Any pop_back(), erase(), etc. operations will have the wrong effect. I strongly suggest using Boost.

One may think of using a container of auto_ptr. Contrarily, this is a bad idea; the copy-semantics of an auto_ptr prevent it from working. The best option is to get rid of the dynamic allocation, if possible.

GMan
I dont know if we can use autopointers in a vector.http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
Samrat Patil
@Sammy, cannot use `auto_ptr` in STL containers. **Can** do so with the boost pointer container lib.
vladr
@GMan, the last `container_wrapper` claim can be misleading; the OP still has to worry if ever he decides to call `v.container.erase`, `v.container.clear` etc.
vladr
@Vlad: I agree, I'll mention it.
GMan
+1 after the update.
vladr