自定义分配器指针偏离多重继承

时间:2017-02-09 20:43:48

标签: c++ pointers memory-management

我想知道在为C ++使用自定义分配器时解决指针偏移问题的最佳方法是什么。我们来看一个例子:

struct A { int i; virtual ~A() = default; };
struct B { int j; virtual ~B() = default; };
struct C : A, B { int k; virtual ~C() = default; };

auto p1 = std::make_unique<C>();
std::unique_ptr<B> p2 = std::move(p1);

在这种情况下,由于应用了多重继承偏移,p2.get()p1.get()不同。如果两个unique_ptrs都使用自定义删除器,它将包含的指针转发给某个自定义分配器,则deallocate的指针将不同于从分配返回的指针,这是有问题的。

为了解决这个问题,我做了一个解决方法删除操作,基本上调用了一个执行正确转换的lambda:

template<class T>
class MemoryManagerDeleter
{
public:
    MemoryManagerDeleter(MemoryManagerPtr manager) noexcept
        : mMemoryManager{std::move(manager)}
        , mDeleteFunc{[=](auto pointer) {
            pointer->~T();
            mMemoryManager->deallocate(pointer);
        }}
    {
        assert(mMemoryManager);
    }

    template<class U>
    MemoryManagerDeleter(const MemoryManagerDeleter<U> &other) noexcept
        : mMemoryManager{other.mMemoryManager}
        , mDeleteFunc{[=](auto pointer) {
            const auto cast = static_cast<U *>(pointer);

            cast->~U();
            mMemoryManager->deallocate(cast);
        }}
    {
        assert(mMemoryManager);
    }

    MemoryManagerDeleter(const MemoryManagerDeleter &) = default;

    inline void operator()(T *pointer) const noexcept
    {
        if (pointer != nullptr)
            mDeleteFunc(pointer);
    }

    MemoryManagerDeleter &operator =(const MemoryManagerDeleter &) = default;

private:
    MemoryManagerPtr mMemoryManager;
    std::function<void (T *)> mDeleteFunc;

    template<class> friend class MemoryManagerDeleter;
};

必须有更好的方法来做到这一点。感觉就像一个可怕的黑客。

0 个答案:

没有答案