Search code examples
c++operator-overloadingnew-operator

Operator new implementation visibility issue


It's said that, as a good practice, when implementing one of the forms of the operator new for a class, it is recommended that all the others forms also must be implemented. If don't, due to c++ not intuitive visibility rules, bad things can happen. What are these bad things and how do they happen? Can the not implemented forms get hidden?


Solution

  • I assume you're talking about overloading the global operator new function versus a class-specific operator new.

    TL;DR: If you want to have fine-grained memory control, you may wish to consider using an Allocator paradigm, like the standard containers. The rules are complicated and error-prone.

    The most common reason to implement all of them is due to the confusing calling contexts. Often, the class-specific new will be implemented in terms of the global operator. However, this is not required, so you can get surprised.

    For example, let's say you wrote class A and class B and you want to control allocation. You write overrides for A and B.

    void *very_clever_allocator(size_t sz);
    
    class A {
        void* operator new(size_t sz) {
            return very_clever_allocator(sz);
        }
    };
    
    class B {
        void* operator new(size_t sz) {
            return very_clever_allocator(sz);
        }
    };
    

    A well-intentioned user of your code writes:

    void *operator(size_t sz) {
        return incompatible_allocator(sz);
    }
    

    If someone allocates your class with ::new A; then the class-specific version is ignored. So all of a sudden, a different allocator is used. The programmer may not be careful, and calls delete. Since you are careful, you have also defined operator delete. But now, your very_clever_allocator doesn't know about this object. This will be a hard to diagnose bug.

    This is not common, but since these rules are very complicated, it's usually easier to use an Allocator. If you're just writing code to debug, this is OK for a one time thing.

    More reading: https://eli.thegreenplace.net/2011/02/17/the-many-faces-of-operator-new-in-c