Generically overloading operator new while conside

2019-06-02 17:20发布

问题:

Situation

I am writing a memory manager for dynamic memory (de)allocations. For a class A to use it when operator new (or delete) is called, it is sufficient for class A to inherit from a class CustomAllocate, which itself overloads new and delete in a way that uses the memory manager.

Problem

However, apparently I completely missed out on alignment requirements. Unfortunately, CustomAllocate::new has no information about how a class A inheriting from it should be aligned as the only parameter is the size of the requested memory. I am searching for a way to include alignment information without having to overload new (and delete) in every class A to use the memory manager.

Idea 1 (and why it does not work)

Templating class CustomAllocate with an integer value representing the alignment requirements and inheriting like so: class A : public CustomAllocate< alignof(A) >.

Impossible because alignof(A) cannot be known at the time it has to be passed as template parameter, even though the passed parameter should never change the alignment requirements of class A.

Idea 2 (and why it does not work)

Having a pure virtual function virtual int CustomAllocate::getAlignment() = 0 that is implemented in every class A by copy pasting something like return alignof(A);.

Impossible because new is static and thus can never access a virtual function.


Any working ideas?

回答1:

Somewhat to my surprise, the following seems to work:

template <typename T> class CustomAllocate
{
public:
    void* operator new (std::size_t count)
    {
        std::cout << "Calling new, aligment = " << alignof (T) << "\n";
        return aligned_alloc (alignof (T), count);
    }

    void operator delete (void *p)
    {
        std::cout << "Calling delete\n";
        free (p);
    }
};

Test program:

class A : public CustomAllocate <A>
{
public:
    A (int a, int b) : a (a), b (b) { }
    int a, b;
};

int main ()
{
    A *x = new A (1, 2);
    std::cout << x->a << ", " << x->b << "\n";
    delete x;
}

Output:

Calling new, aligment = 4
1, 2
Calling delete

Live Demo