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?
- Yes
- 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 thenew
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. - 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
Disabling G++'s Return-Value Optimisation
Link Error "Undefined Reference to '_Gxx_Personality_V0'" and G++
Why Should I Initialize Member Variables in the Order They'Re Declared In
How to Iterate Over a Constant Vector
How to Construct an Iso 8601 Datetime in C++
How to Initialize and Print a Std::Wstring
How to Use Sendinput Function C++
Libzip with Visual Studio 2010
Version 'Cxxabi_1.3.8' Not Found (Required by ...)
How to Validate That a String Is a Valid Ipv4 Address in C++
Why Can't I Inherit from Int in C++
C++ Implicit Conversion (Signed + Unsigned)
What Is the Performance Impact of Using Int64_T Instead of Int32_T on 32-Bit Systems
Why Isn't 'Std::Initializer_List' Defined as a Literal Type