重载“operator new”想要查看它分配的类型

时间:2014-02-26 23:54:59

标签: c++11 coding-style new-operator

这看起来应该是显而易见的,但我对它有所了解。我有

class SimpleMemoryPool {
    char buffer[10000];
    size_t idx;
    void *Alloc(size_t nbytes) { idx += nbytes; return &buffer[idx - nbytes]; }
};

inline void* operator new (size_t size, SimpleMemoryPool& pool)
{
    return pool.Alloc(size);
}

inline void* operator new[] (size_t size, SimpleMemoryPool& pool)
{
    return pool.Alloc(size);
}

我的想法是,我可以从SimpleMemoryPool中分配新对象,然后在SimpleMemoryPool被销毁时它们全部被“释放”:

void foo()
{
    SimpleMemoryPool pool;
    int *arr = new (pool) int[10];
    double *arr2 = new (pool) double(3.14);
    ...do things with arr and arr2...
    return;  // and arr, arr2 are "released" at this point
}

我已经简化了一个挑剔:上面的代码是粗略的,因为double不会是8字节对齐的。别担心;我的真实SimpleMemoryPool代码返回最大对齐块。

接下来你可能会想到下一件事:“谁叫召唤者?!”即,如果我不小心写了

    std::string *arr3 = new (pool) std::string;

然后我处于一个受伤的世界,因为编译器会为我生成std::string::string()的调用,但没有人会调用std::string::~string()。内存泄漏,随之而来的是坏事。

这是我想要解决的问题。我想要做的基本上是

class SimpleMemoryPool {
    ...
    // (std::enable_if omitted for brevity)

    template<typename T, typename... Args>
    T *New(Args... args) {
        static_assert(std::is_trivially_destructible<T>::value, "T must be trivially destructible!");
        void *ptr = this->Alloc(nelem * sizeof (T));
        return new (ptr) T(std::forward<Args>(args)...);
    }

    template<typename ArrayT>
    auto NewArray(size_t nelem) -> std::remove_extent<ArrayT>::type {
        typedef typename std::remove_extent<ArrayT>::type T;
        static_assert(std::is_trivially_destructible<T>::value, "T must be trivially destructible!");
        void *ptr = this->Alloc(nelem * sizeof (T));
        return new (ptr) T[ nelem ];
    }
};

...

    int *arr = pool.NewArray<int>(10);
    double *arr2 = pool.New<double>(3.14);
    std::string *arr3 = pool.New<string>();  // fails the static_assert, hooray!

这种方法的问题在于它很难看。它看起来很糟糕,它邀请后来的维护者来加入并通过添加“适当的”operator new来“修复”代码,此时我们失去了static_assert的安全性。

有没有办法充分利用这两个方面 - 通过static_assert进行类型安全,还有一个很好的语法?

  • 您可以假设C ++ 11。我也欢迎C ++ 14答案,即使它们对我没有立即有用。

  • 将成员operator new添加到我的所有课程(在此示例中为intdouble)是不可接受的。无论我做什么都必须开箱即用而不需要改变一百万行代码。

  • 这可能是Get type of object being allocated in operator new的副本,但我仍然喜欢为这个特定用例量身定制的答案。可能有一些我不知道的好习语。

0 个答案:

没有答案