How to Erase & Delete Pointers to Objects Stored in a Vector

How to erase & delete pointers to objects stored in a vector?

You need to be careful because erase() will invalidate existing iterators. However, it will return a new valid iterator you can use:

for ( it = Entities.begin(); it != Entities.end(); ) {
if( (*it)->getXPos() > 1.5f ) {
delete * it;
it = Entities.erase(it);
}
else {
++it;
}
}

Does vector::erase() on a vector of object pointers destroy the object itself?

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;
}

How do i remove a pointer to an object in c++ from a vector dynamically?

You can use std::remove and std::erase on any std container to remove content:

Shot* to_be_removed = ...;
std::vector<Shot*>::iterator i = std::remove(shots.begin(),shots.end(),to_be_removed);
std::erase(i,shots.end());
delete (to_be_removed);//don't forget to delete the pointer

This works when you know the element you want to remove. If you don't know the element you must find a way to identify the elements you want removed. Also if you have a system to identify the element it could be easier to use the container iterator in order to do the removal:

std::vector<Shot*>::iterator i = ...;//iterator the the element you want to remove
delete (*i);//delete memory
shots.erase(i);//remove it from vector

Lastly if you want to remove all pointers from the container and delete all the items at the same time you can use std::for_each

//c++ 03 standard:
void functor(Shot* s)
{
delete(s);
}

std::for_each(shots.begin(),shots.end(),functor);
shots.clear();//empty the list

//or c++11 standard:
std::for_each(shots.begin(),shots.end(),[] (Shot * s){ delete(s); } );
//the rest is the same

How to delete a pointer belonging to an object stored in a vector?

Using RAII(Resource Acquisition is Initialization)

Add a destructor to the Contained class:

Contained::~Contained() {
delete data;
}

This will ensure whenever your contained object goes out of scope, it will automatically delete the data pointer it has. So if you do

//delete first element
rooms.erase(rooms.begin());

data ptr of that object will automatically be deleted.

Using smart pointers

Use std::unique_ptr<T>.

class Contained {
private:
std::unique_ptr<Data> data;
public:
Contained();
// what should I add ? a copy constructor ? an assignement operator ? and how
};

and in the constructor:

Contained::Contained() {
data = std::make_unique<Data>();
}

Using smart pointers i.e., (unique_ptr, shared_ptr) ensures your pointer will automatically delete when no one is owning it. Since you can not copy unique_ptr but only move it, you should define a move constructor and move assignment operator on the Contained class.

Contained::Contained(Contained&& other) 
: data(std::move(other.data))
{}

Contained& operator=(Contained&& rhs) {
if (this != &other) {
data = std::move(rhs.data);
}
return *this;
}

Deleting an element from a vector of object pointers allocated on the stack

If you want to delete pointer element, delete will call object destructor. No need to call
List[id]->~Ball() also no need to set pointer to NULL as you are going to erase the element anyway.

std::vector<Ball*> List;

void BallManager::DeleteBall(int id)
{
if (id < List.size()) // should check id is still in range
{
delete List[id];
List.erase(List.begin()+id);
}
}

Strongly recommand you use smart pointer as Chris mentioned, then you don't need to worry about deleting object pointer when you delete element from STL container, demo as below:

  std::vector<std::shared_ptr<Ball> > List;
void BallManager::DeleteBall(int id)
{
if (id < List.size()) // should check id is still in range
{
List.erase(List.begin()+id);
}
}

What do I need to do before deleting elements in a vector of pointers to dynamically allocated objects?

  1. Yes
  2. Vectors are implemented using template memory allocators that take care of the memory management for you, so they are somewhat special. But as a general rule of thumb, you don't have to call delete on variables that aren't declared with the new keyword because of the difference between stack and heap allocation. If stuff is allocated on the heap, it must be deleted (freed) to prevent memory leaks.
  3. No. You explicitly have to call delete myVec[index] as you iterate over all elements.

Ex:

for(int i = 0; i < myVec.size(); ++i)
delete myVec[i];

With that said, if you're planning on storing pointers in a vector, I strongly suggest using boost::ptr_vector which automatically takes care of the deletion.

Remove and delete pointers that match a condition in a vector

std::unique_ptr does the deletion for free:

std::vector<std::unique_ptr<GameObject>> gameObjects;

// Remove objects from vector
gameObjects.erase(
std::remove_if(
gameObjects.begin(),
gameObjects.end(),
[](const auto& p) { return p->isDestroyed(); }
),
gameObjects.end()
);

I suggest to use it instead. It also avoids mistakes like forgetting to delete or double deleting.

How to remove object from a vector if it was deleted

From your sample code, I assume your vector is defined somewhat like this:

std::vector<YourType*> entities;

Therefore, your vector does not contain YourType objects, but pointer to YourType. That is, the elements the vector manages are the pointers, not the pointed objects.

Thus when you do this delete entities[x + y * width]; you indeed delete the YourType instance, but the pointer still exists and it sill in your vector.

It might be easier to visualize if you decompose that statement to the equivalent 2 lines:

YourType * pointer = entities[x + y * width];
delete pointer;

To actually remove the pointer from the vector, you need to say so:

entities.erase(entities.begin() + x + y * width);

This would remove the pointer from the array (also shifting all things past that index). You still need to do the delete yourself as, again, the vector is only managing the pointer, not the YourType.


Note that unless you have a good reason, you should probably not store the pointer in the vector, but the object itsself. That would remove your confusion:

std::vector<YourType> entities;

// deleting a YourType:
entities.erase(entities.begin() + x + y * width);

No delete or new anymore, because the object is directly in the vector. So the vector manages it for you instead of just managing the pointer and letting you deal with the pointed object.


Update after question edit:

In your case, you do have a good reason, because you actually store a non-owning pointer. So it might make sense that entities and projectiles store pointers, so they actually point at the same objects.

So both vectors will manage their pointers, but you have to think of how the lifecycle of those two pointers (the one from entities and the one from projectiles) interact with the object itself.

Deleting the object will not get rid of the pointers, in neither of the arrays.

Having trouble deleting vector of pointers

Erasing an element from the vector invalidates the iterator, so you can't continue iterating afterwards. In this case, I wouldn't erase elements within the loop; I'd clear the vector afterwards:

for (auto it = gamestates_.begin(); it != gamestates_.end(); ++it){
delete *it;
}
gamestates_.clear();

Although, if this is in the destructor and the vector is about to be destroyed, there's no point clearing it either.

If you do need to erase within a loop (perhaps because you only want to erase some elements), then you need a bit more care to keep the iterator valid:

for (auto it = gamestates_.begin(); it != gamestates_.end();){ // No ++ here
if (should_erase(it)) {
it = gamestates_.erase(it);
} else {
++it;
}
}

One thing I haven't tried yet is using unique_ptr but I'm sure this should be able to handle it without using them. Please correct me if I'm wrong.

If you do want to manage dynamic objects by steam by this, then make sure you follow the Rule of Three: you'll need to implement (or delete) the copy constructor and copy-assignment operator to prevent "shallow" copying leaving you with two vectors that try to delete the same objects. You'll also need to take care to delete the objects in any other place that removes or replaces them. Storing smart pointers (or the objects themselves, if you don't need pointers for polymorphism) will take care of all these things for you, so I would always recommend that.

I'm aware I should clear the vector after the loop but this is what I've come to after trying every normal method of deleting the pointers. It doesn't seem to like the delete command.

The most likely cause is that you're not following the Rule of Three, and are accidentally trying to delete the same objects twice after copying the vector. It's also possible that GameState is a base class and you forgot to give it a virtual destructor, or that the pointers have been corrupted by some other code.

Deallocating objects stored in a vector?

It depends on how vector is defined.

If maps is a vector<myClass*> you delete each element with something similar to:

for ( i = 0; i < maps.size(); i++)
{
delete maps[i];
}

If maps is a vector<myClass> I don't think you need to delete the individual elements.



Related Topics



Leave a reply



Submit