智能指针和派生类

Smart pointers and derived classes

本文关键字:派生 指针 智能      更新时间:2023-10-16

我将在std::list中存储大量对象。

由于我需要这些对象来存储不同类型的数据,所以我存储指向一个基类的指针,该基类只保存enum类型的属性,该属性"告诉"对象它应该被广播到哪个派生类。每个派生类都有自己的数据类型:

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

为了保存指向这些对象的指针,我使用了智能指针:

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

然而,虽然每个Base对象都知道应该将其强制转换为什么类型才能正确删除,但智能指针只知道它必须调用Base的析构函数。这将使每个子类分配的内存无法删除。

如何将自定义deleter传递给智能指针,以便它们知道如何正确地转换和释放每个对象的内存?我应该实现什么自定义deleter?

只需将Base的析构函数标记为virtual即可。然后,默认的deleter将调用delete pointer_to_raw_object;,它将根据object的动态类型调用正确的析构函数。

示例:

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

在Coliru上直播

PS:考虑使用std::list::emplace_back来获得更干净(更高效(的代码。