Reputation: 345
I'm new to C++ and have a question regarding memory management.
In the header, I have this:
std::vector<Obstacle::Obstacle*> obstacles;
and in the .cpp I do this:
Circle *circle = new Circle(x, y, radius);
obstacles.push_back(circle);
where Circle
is a subclass of Obstacle
.
My question is when should I call delete
on the elements which are in the vector? I have heard each new
should be balanced by a delete
. Do I need to in the destructor loop through the vector and call delete
on each element? Isn't there a more elegant way?
Thanks
Upvotes: 0
Views: 294
Reputation: 227390
You have to call delete
on the elements before you clear the vector, or before the vector goes out of scope iff the vector owns the objects pointed at. A more elegant solution is to have the vector hold smart pointers. The particular type of smart pointer should depend on the ownership policy.
For example, a vector owning the pointed-at objects should use C++11 std::unique_ptr
:
std::vector<std::unique_ptr<Obstacle>> obstacles;
Of course, all of the above is under the assumption that you actually have strong reasons to use pointers. Often the best solution is the simplest ones: hold items by value:
std::vector<SomeType> things;
Note that this doesn't apply in your case, where you are storing pointers to objects derived from a base class, since storing values of base type would result in object slicing.
Edit: One simple way to ensure the elements are deleted when the vector goes out of scope is to write a scope guard class:
template <typename CONTAINER>
struct PtrContainerGuard
{
PtrContainerGuard(CONTAINER& container) : c_(container) {}
~PtrContainerGuard()
{
for (typename CONTAINER::iterator it = c_.begin(); it != c_.end(); ++it)
delete (*it);
}
private:
CONTAINER& c_;
}
then
std::vector<Obstacle*> obstacles;
PtrContainerGuard<std::vector::Obstacle*> p(obstacles);
Upvotes: 10
Reputation: 487
Why not use shared_ptr? You don't have to create new objects and worry about deleting them if you use them.
typedef shared_ptr<Obstacle> ObstaclePtr;
int main()
{
std::vector<ObstaclePtr> obstacles;
//Create objets using shared_ptr and push them in vector
ObstaclePtr obstacle1(new Circle());
obstacles.push_back(obstacle1);
ObstaclePtr obstacle2(new Circle());
obstacles.push_back(obstacle2);
//When vector obstacles goes out of scope here, all circles inside are destructed!
}
Upvotes: 0
Reputation: 247919
Yes, there is a more elegant way. Throw away all your pointers.
std::vector<Obstacle::Obstacle> obstacles;
Circle circle(x, y, radius);
obstacls.push_back(circle);
Nothing was new
'ed, nothing needs to be delete
d, you save a memory allocation, and access to the objects stored in the vector becomes more efficient.
Also, your code will no longer make the eyes bleed of more experienced C++ developers.
All in all, I call that a win. :)
Upvotes: -1