我想知道在为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;
};
必须有更好的方法来做到这一点。感觉就像一个可怕的黑客。