How could I sensibly overload placement operator new?

后端 未结 9 1987
北恋
北恋 2020-12-05 23:49

C++ allows overloading operator new - both global and per-class - usual operator new, operator new[] used with new[] stat

相关标签:
9条回答
  • 2020-12-06 00:16

    Technically, a placement operator new is any operator new that takes additional arguments besides the size of the memory needed.

    So, new(std::nothrow) X uses a placement operator new and so does new(__FILE__, __LINE__) X.

    The only reason for overriding the operator new(size_t, void*) could be to add tracing information, but I think the need for that will be pretty low.

    0 讨论(0)
  • 2020-12-06 00:20

    The most important extra-functionality for placement new overload would be to check address alignment.

    For example, lets assume some class requires 16-bytes alignment. Developer overloads new, new[], delete and delete[] - just to be sure everything is aligned properly.

    Everything works fine to the moment when he tries to use his class with library which uses placement new... Library has no idea if/what alignment is required for the class and address it tries to "place" the object to might not be aligned - big boom.

    The simplest example of such situation - try using std::vector<T> where T requires non-standard alignment.

    Overload for placement new allows to detect if pointer is not aligned - might save hours of debugging.

    0 讨论(0)
  • 2020-12-06 00:20

    My primary usage is to create a large array of objects. Its performing much better and has less overhead to allocate the memory in a whole block, i.e. using VirtualAlloc from Win32 (when programming windows). Then you just pass a ptr within that block to each objects placement new such as:

    char *cp = new char[totalSize];
    
    for(i = 0; i < count; i++, cp += ObjSize)        
    {                                                        
        myClass *obj = new(cp) myClass;             
    }
    
    0 讨论(0)
  • 2020-12-06 00:23

    One example is at Stroustrup's FAQ.

    0 讨论(0)
  • 2020-12-06 00:30

    I'm not exactly sure of the question, but the following overrides placement new at the class level:

    struct Bar {
    void* operator new(size_t /* ignored */, void* where) throw() { return where; }
    };
    
    int main() {
      char mem[1];
      Bar* bar = new(mem) Bar;
    }
    

    I believe this is legal C++ (and compiles and runs fine with gcc 4.4.6).

    You are free to change the implementation of this operator as you see fit (including removing the throw() clause, which will mean the compiler no longer checks the where pointer for null before calling the constructor). Tread carefully though.

    §18.4.​1.3 is interesting. I believe this just applies to the global operator new function, not class specific ones.

    0 讨论(0)
  • 2020-12-06 00:33

    I've seen an example where two-argument new [] was overwritten to return memory blocks pre-filled with the char passed as the additional argument. I don't remember what the original code used (probably memset()), but it was functionally something like this:

    #include <iostream>
    #include <algorithm>
    #include <new>
    void* operator new [](size_t n, char c)
    {
            char* p = new char[n];
            std::fill(p, p+n, c);
            return p;
    }
    int main()
    {
            char* p = new('a') char[10];
            std::cout << p[0] << p[1] << ".." << p[9] << '\n';
    }
    

    although I guess this wouldn't be called "placement" new because it does not perform placement. It could probably be useful if templated so that it can build arrays of any type, filled with a copy of the object passed as its second argument... but then, we have containers for that anyway.

    0 讨论(0)
提交回复
热议问题