I am developing a game in C++, and have been using vectors of smart pointers to store some level data. The game runs and works without issue, but I was wondering whether or not the memory held by the pointers is actually being automatically freed or not. Below is a simplified version of my code structure as an example.
I have a struct Level
and three classes Game
, Enemy
, and Grunt
(which inherits from Enemy
). Within the struct, I have a vector
of smart pointers of type Enemy
, and in Game
I have created a Level
as a member as follows:
#include <vector>
#include <memory>
class Enemy
{
};
class Grunt : public Enemy
{
public:
Grunt() {}
~Grunt() {}
};
struct Level
{
std::vector<std::shared_ptr<Enemy>> eVector;
};
class Game
{
private:
Level level1 = {{std::make_shared<Grunt>()}};
};
int main()
{
Game g;
}
A Game
object is created in my main()
, which is used to begin the game loop.
Throughout my code, I am using level1
to access the vector
. My question is that, since it is a member variable of the class Game
and therefore never goes out of scope, are the smart pointers in the vector
still being automatically freed or not? If not, how would I best go about freeing them manually?
The elements of a std::vector
remain in memory as long as they are still in the vector. If you remove an element, it will be destroyed. When the vector itself is destroyed, any remaining elements in it will be destroyed.
In this case, the vector elements are shared_ptr
objects. Destroying a shared_ptr
decrements the reference count of the thing it is pointing at. When the reference count falls to 0, that thing will be destroyed.
While the Game
object remains alive in scope, its Level
member is alive, and its std::vector
member is alive, and any shared_ptr
elements in it are alive.
When the Game
object goes out of scope, it is destroyed, which destroys its Level
member, which destroys its vector
member, which destroys its shared_ptr
elements, which destroys their pointed-at Enemy
objects.
On a side note: your Enemy
type should have a virtual
destructor to ensure derived objects are destroyed properly when calling delete
on an Enemy*
pointer. This is not a problem for std::shared_ptr
specifically when created with a derived type like Grunt
, but it is a problem for std::unique_ptr
and raw pointers, so it is something you should be aware of.