用虚方法实例化类,但不进行堆分配

Instantiating a class with virtual methods without a heap allocation

本文关键字:分配 方法 实例化      更新时间:2023-10-16
class Base
{
public:
    virtual ~Base() {}
    virtual void Foo() = 0;
};
class FirstDerived: public Base
{
public:
    void Foo() { cout << "FirstDerived" << endl; }
};
class SecondDerived: public Base
{
public:
    void Foo() { cout << "SecondDerived" << endl; }
};
union PreallocatedStorage
{
    PreallocatedStorage() {}
    ~PreallocatedStorage() {}
    FirstDerived First;
    SecondDerived Second;
};
class ContainingObject
{
public:
    Base* GetObject()
    {
        if (!m_ptr)
        {
            // TODO: Make runtime decision on which implementation to instantiate.
            m_ptr = new(&m_storage) SecondDerived();
        }
        return m_ptr;
    }
    ~ContainingObject()
    {
        if (m_ptr)
        {
            m_ptr->~Base();
        }
    }
private:
    PreallocatedStorage m_storage;
    Base* m_ptr = nullptr;
};
int main()
{
    auto object = make_unique<ContainingObject>();
    // ...
    // Later, at a point where I don't want to make more heap allocations...
    // ...
    auto baseObject = object->GetObject();
    baseObject->Foo();
    return 0;
}

我想达到的目的:

  • 我需要实例化一个具有虚拟方法的类。
  • 在我确切地知道要实例化哪个派生类的时间点上,我不能进行进一步的堆分配(这只是出于好奇,所以确切的原因无关)。
  • 因此,我想以某种方式预先分配足够的空间来容纳任何可能的实现,然后再决定我要在其中实例化什么类。

上述代码中是否存在任何不符合标准/未定义的行为?

代码正确。请参阅对该问题的评论,以获得一些有趣的见解,特别是std::aligned_union的使用,它可以用作上述PreallocatedStorage联合的通用替代品。