I am going to store a large quantity of objects in a std::list
.
Since I need those objects to store different types of data, I am storing pointers to a base class which only holds an attribute of an enum
type which tells the objects to which of the derived classes it should be casted to. Each derived class has then its own type of data:
struct Base {
enum class Type {
D1,
D2,
...
} type;
Base(Type new_type):
type(new_type) {}
};
struct D1: public Base {
std::string data;
D1(std::string new_data):
Base(Base::Type::D1), data(new_data) {}
};
struct D2: public Base {
double data;
D2(double new_data):
Base(Base::Type::D2), data(new_data) {}
};
To hold pointers to these objects, I am using smart pointers:
std::list<std::unique_ptr<Base>> list;
list.push_back(std::unique_ptr<Base>(new D1("Somestring")));
list.push_back(std::unique_ptr<Base>(new D2(3.14)));
However, while each Base object knows what type it should be casted to to get deleted properly, the smart pointer only knows that it must call Base's destructor. Which would leave undeleted the memory each subclass allocated.
How would I pass a custom deleter to the smart pointers so that they know how to properly cast and free each object's memory? What should I implement that custom deleter?
Just mark the destructor of Base
as virtual
. Then the default deleter will invoke delete pointer_to_raw_object;
, which will call the right destructor based on the dynamic type of object
.
Example:
#include <iostream>
#include <memory>
#include <list>
struct Base
{
virtual ~Base(){std::cout << __PRETTY_FUNCTION__ << std::endl;}
};
struct Derived : Base
{
~Derived() override {std::cout << __PRETTY_FUNCTION__ << std::endl;}
};
int main()
{
std::list<std::unique_ptr<Base>> l;
l.emplace_back(new Base);
l.emplace_back(new Derived);
}
Live on Coliru
PS: consider using std::list::emplace_back
for cleaner (and more efficient) code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With