54

I have a vector of pointers to objects. I need to remove an element from the vector and place that element in another list.

I read that erase can be used to remove the object from the vector, but I also read that it calls the objects destructor before doing so.

I need to know whether or not erasing the object will destroy it as well.

2

5 Answers 5

80

vector::erase
Removes from the vector container and calls its destructor but If the contained object is a pointer it doesnt take ownership of destroying it.

You will have to explicitly call delete on each contained pointer to delete the content it is pointing to, for example:

void clearVectorContents( std::vector <YourClass*> & a ) { for ( int i = 0; i < a.size(); i++ ) { delete a[i]; } a.clear(); } 

Storing raw pointers in standard containers is not a good idea. If you really need to store resources that have to be allocated by new, then you should use boost::shared_ptr. Check out the Boost documentation.

An more generic & elegant solution:
This solution makes use of for_each & templates as @Billy pointed out in comments:

// Functor for deleting pointers in vector. template<class T> class DeleteVector { public: // Overloaded () operator. // This will be called by for_each() function. bool operator()(T x) const { // Delete pointer. delete x; return true; } }; 

And this can be called as:

for_each( myclassVector.begin(),myclassVector.end(), DeleteVector<myclass*>()); 

where, myclassVector is your vector containing pointers to myclass class objects.

Usage Example:

#include "functional" #include "vector" #include "algorithm" #include "iostream" //Your class class myclass { public: int i; myclass():i(10){} }; // Functor for deleting pointers in vector. template<class T> class DeleteVector { public: // Overloaded () operator. // This will be called by for_each() function. bool operator()(T x) const { // Delete pointer. delete x; return true; } }; int main() { // Add 10 objects to the vector. std::vector<myclass*> myclassVector; for( int Index = 0; Index < 10; ++Index ) { myclassVector.push_back( new myclass); } for (int i=0; i<myclassVector.size(); i++) { std::cout << " " << (myclassVector[i])->i; } // Now delete the vector contents in a single line. for_each( myclassVector.begin(), myclassVector.end(), DeleteVector<myclass*>()); //Clear the vector myclassVector.clear(); std::cout<<"\n"<<myclassVector.size(); return 0; } 
Sign up to request clarification or add additional context in comments.

10 Comments

so does that mean that if it's a vector of pointers, the destructor won't be called?
+1 for being complete, saying "but If the contained object is a pointer it doesnt take ownership of destroying it."
@anonymous That's right. The pointer itself will get destroyed, but it's up to the programmer to explicitly free the memory to which it refers (assuming the memory isn't used elsewhere).
Thanks for the tip on boost. It may be helpful in the future. I'm currently using a game engine, cocos2d-x, and it supposedly performs garbage collection automatically.
oh and because your answer covered everything, I chose yours. Thanks!
|
15
  • If you have a vector<MyObject> then MyObject::~MyObject will be called.
  • If you have a vector<MyObject*> then delete <MyObject instance> will not be called.

To move MyObject between two vectors, you need to first insert it into the destination vector, then erase the original. Note that this will create a new copy of the object. When moving pointers, you can just keep the pointer in a temporary variable, erase it from the vector, then insert wherever you need.

And here's another simple way to delete and then remove all the items in a vector:

template<class T> void purge( std::vector<T> & v ) { for ( auto item : v ) delete item; v.clear(); } 

Comments

2

Yes, erase destroys the element. However, if you're placing the element in another container you probably made a copy putting it into that other container. The only way you'd run into issues is if you copied a pointer or something like that into the other container.

4 Comments

Yeah, I'm using a vector of pointers to objects. Sorry, I didn't clarify that.
@anonymous: Ah, well the "destructor" of the pointer would be called then. Which of course, does nothing. The vector destroys what it actually contains, not anything referenced from there. (Note that means you have to go back and delete those manually)
oh ok, so just to clarify, if I have: vector<Plane *> p, q; Plane *r = new Plane(); p.push_back(r); q.push_back(r); p.erase(p.begin()); r and q.begin() would still reference the newly created Plane?
It's the same behaviour as if you just wrote { Plane * p = new Plane; }, when p goes out of scope it is "destroyed" but the allocated object still lives on the heap. Using naked pointers makes them your responsibility.
1

Yes. vector::erase destroys the removed object, which involves calling its destructor.

Comments

1

Yes, of course it will. If the object doesn't exist in the vector, where else would it exist?

Edit: This will not delete anything pointed to by a pointer. You should use automatic life-time managing pointers such as shared_ptr to manage object lifetimes.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.