Search code examples
c++memory-managementmaintainability

Create myNew/myDelete to replace new/new[]/delete/delete[]


How to code my program to has flexibility to receive custom allocator in advance?

I coded some allocators, but not sure whether I will really need it.
However, I know for sure that if my custom allocator will be plugged-in, I want to use it in some certain parts.

Example

For example, int* B::db should use custom allocator (myNew/myDelete),
while all std::vector should use standard allocator.

While I still don't plug my custom allocator, I wish my program will use standard new/delete as default.

#define myNew new
#define myDelete delete
class B{ //B should not be a template class
    int* db=nullptr;
    std::vector<float> something; //<- let it use default new/delete
    public: B(){
        db=myNew int[5];   //work like "db=new int[5];"
    }
    public: ~B(){
        myDelete[] db;     //work like "delete[] db;"
    }
};

If I want plug a custom allocator later, I can just change the #define.

Note: B should not be a template class.

Question

I am not sure if this is a correct way. I am still very new to allocator.
I also want to avoid macro if possible.
Is it a good solution? Are there solutions without macro?

I can let my program just use new/delete as default, and I can refactor it later.
However, it will probably be a mental-breaking work in the future.

Note: Most Q/A seem to focus on overloading the global new/delete. That is not what I want. :-

Sorry if this question is too newbie.
I haven't found any good tutorial/information about using allocator in real practice.

I have also read (they are just theory of allocator + code) :-


Solution

  • B may have to stay a non-template. But it doesn't mean you can't write a template to help. And you may as well facilitate RAII while you're at it.

    template<typename T>
    class my_new_heap_array {
      T *ptr;
    public:
      operator T*() const { return ptr; }
    
      my_new_heap_array(std::size_t sz) 
        : ptr(myNew T[sz])
      {}
    
      ~my_new_heap_array() { myDelete[] ptr; }
    };
    
    class B { //B should not be a template class
        my_new_heap_array<int> db;
        std::vector<float> something; //<- let it use default new/delete
        public:
        B()
          :db(5)
        { }
    };
    

    In general, so long as you program with separation of concerns in mind, you'd find it easier to change behaviors more easily. B needs to decide on what allocator to use, but it shouldn't be concerned with how to use it. That concern falls on the helper class. And if B needs to use another allocator some day, then just switch out the helper class for another.