tags:

views:

1323

answers:

7

I'm trying to delete everything from a std::vector by using the following code

vector.erase( vector.begin(), vector.end() );

but it doesn't work, help!


Update: Doesn't clear destruct the elements held by the vector? I don't want that, as I'm still using the objects, I just want to empty the container

+17  A: 

I think you should use clear:

vector.clear();


EDIT:

Doesn't clear destruct the elements held by the vector?

Yes it does. It calls the destructor of every element in the vector before returning the memory. That depends on what "elements" you are storing in the vector. In the following example, I am storing the objects them selves inside the vector:

class myclass
{
public:
    ~myclass()
    {

    }
...
};

std::vector<myclass> myvector;
...
myvector.clear(); // calling clear will do the following:
// 1) invoke the deconstrutor for every myclass
// 2) size == 0 (the vector contained the actual objects).

If you want to share objects between different containers for example, you could store pointers to them. In this case, when clear is called, only pointers memory is released, the actual objects are not touched:

std::vector<myclass*> myvector;
...
myvector.clear(); // calling clear will do:
// 1) ---------------
// 2) size == 0 (the vector contained "pointers" not the actual objects).

For the question in the comment, I think getVector() is defined like this:

std::vector<myclass> getVector();

Maybe you want to return a reference:

// vector.getVector().clear() clears m_vector in this case
std::vector<myclass>& getVector();
AraK
If your vector contains pointers, this will not release memory but just clear the collection. You have to release memory by yourself.
Patrice Bernassola
@Patrice Sure, but the questioner said nothing about the content of the vector.
AraK
That's why I've added the information. Anyway i agree with your answer.
Patrice Bernassola
It was to do with how I was getting the vectorthis->getVector().clear() didnt workthis->m_vector.clear() workedthanks
michael
@Michael Maybe getVector() returns a **copy** of m_vector not a reference.
AraK
If the OP's problem had really been with v.erase( v.begin(), v.end() ), merely recommending v.clear() wouldn't help as it's no more than an alias for the former.
DevSolar
@michael: Can you post the signature of getVector()?
Naveen
`clear()` generally will not release memory - it just destructs everything and marks it as unused (but bound to the vector). If you want to truly free memory, try `myvector.swap(std::vector<content_type>());`
bdonlan
@bdonlan Although the standards say nothing about the new capacity of a vector after a clear operation, I think you made a good point about how implementations deal with it. I'll edit the post to refer to the size instead of the capacity :)
AraK
+2  A: 

Is v.clear() not working for some reason?

Doesn't clear destruct the elements held by the vector? I don't want that, as I'm still using the objects, I just want to empty the container
michael
@michael: My guess is you are storing pointers in your vector and worried about the actual objects being deleted. Is this correct? In that case, clear() will not delete the actual objects, it will just clear the vector only.
Naveen
`clear()` does not destroy elements held by the vector. It only clear the collection of objects.
Patrice Bernassola
+13  A: 

vector.clear() should work for you. In case you want to shrink the capacity of the vector along with clear then

std::vector<T>(v).swap(v);
aJ
+1 This is an important addition.
luke
Swap it with itself? .. Doesn't one usually swap it with a new empty vector?
Marcus Lindblom
Yes. After clear the vector will be empty. std::vector<T>(v).swap(v) --is a generic way of shrinking the capacity of the vector.
aJ
This technique is also discussed in one of Herb Sutter's "Guru of the Week" articles: http://www.gotw.ca/gotw/054.htm
Void
+4  A: 

vector.clear() is effectively the same as vector.erase( vector.begin(), vector.end() ).

If your problem is about calling delete for each pointer contained in your vector, try this:

#include <algorithm>

template< typename T >
struct delete_pointer_element
{
    void operator()( T element ) const
    {
        delete element;
    }
};

// ...
std::for_each( vector.begin(), vector.end(), delete_pointer_element );

Standard disclaimer: Code written in browser, untested.

DevSolar
In the erase case, I thought the iterator may become invalid after the first erase. Is my understanding correct or am I missing something?
Naveen
He is not clearing the vector, just deleting the elements. I'd suggest additionally setting the pointer values to null, and then clearing the vector afterwards.
Stephen Cox
erase( iterator first, iterator last ); is *defined* to work for spans of elements, which includes the begin()-end() span. I am not 100% sure if v.clear() isn't even officially *defined* in terms of v.erase( v.begin(), v.end() ), but it is definitely at least *functionally* identical.
DevSolar
+2  A: 

Use v.clear() to empty the vector.

If your vector contains pointers, clear calls the destructor for the object but does not delete the memory referenced by the pointer.

vector<SomeClass*> v(0);

v.push_back( new SomeClass("one") );

v.clear();  //Memory leak where "one" instance of SomeClass is lost
Alex B
A: 

If your vector look like this std::vector<MyClass*> vecType_pt you have to explicitly release memory ,Or if your vector look like : std::vector<MyClass> vecType_obj , constructor will be called by vector.Please execute example given below , and understand the difference :

  class MyClass
    {
    public:
        MyClass()
        {
         cout<<"MyClass"<<endl;
        }
        ~MyClass()
        {
         cout<<"~MyClass"<<endl;
        }
    };
    int main() 
    {
        typedef std::vector<MyClass*> vecType_ptr;
        typedef std::vector<MyClass> vecType_obj;
        vecType_ptr myVec_ptr;
        vecType_obj myVec_obj;
        MyClass obj;
        for(int i=0;i<5;i++)
        {
         MyClass *ptr=new MyClass();
         myVec_ptr.push_back(ptr);
         myVec_obj.push_back(obj);
        }
        cout<<"\n\n---------------------If pointer stored---------------------"<<endl;
        myVec_ptr.erase (myVec_ptr.begin(),myVec_ptr.end());
        cout<<"\n\n---------------------If object stored---------------------"<<endl;
        myVec_obj.erase (myVec_obj.begin(),myVec_obj.end());
        return 0;
    }
sat
A: 

If you keep pointers in container and don't want to bother with manually destroying of them, then use boost shared_ptr. Here is sample for std::vector, but you can use it for any other STL container (set, map, queue, ...)

#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>

struct foo
{
    foo( const int i_x ) : d_x( i_x )
    {
        std::cout << "foo::foo " << d_x << std::endl;
    }

    ~foo()
    {
        std::cout << "foo::~foo " << d_x << std::endl;
    }

    int d_x;
};

typedef boost::shared_ptr< foo > smart_foo_t;

int main()
{
    std::vector< smart_foo_t > foos;
    for ( int i = 0; i < 10; ++i )
    {
        smart_foo_t f( new foo( i ) );
        foos.push_back( f );
    }

    foos.clear();

    return 0;
}
Dominic.wig