Overallocating with new/delete

后端 未结 5 1331
面向向阳花
面向向阳花 2020-12-15 12:11

Using malloc and free, it is easy to allocate structures with extra data beyond the end. But how do I accomplish the same with new/

5条回答
  •  佛祖请我去吃肉
    2020-12-15 12:46

    If I were you, I'd use placement new and an explicit destructor call instead of delete.

    template< typename D, typename T >
    D *get_aux_storage( T *x ) {
        return reinterpret_cast< D * >( x + 1 );
    }
    
    int main() {
        char const *hamburger_identity = "yum";
        void *hamburger_room = malloc( sizeof( Hamburger )
                                       + strlen( hamburger_identity ) + 1 );
        Hamburger *hamburger = new( hamburger_room ) Hamburger;
        strcpy( get_aux_storage< char >( hamburger ), hamburger_identity );
        cout << get_aux_storage< char const >( hamburger ) << '\n';
    
        hamburger->~Hamburger(); // explicit destructor call
        free( hamburger_room );
    }
    

    Of course, this kind of optimization should only be done after profiling has proven the need. (Will you really save memory this way? Will this make debugging harder?)

    There might not be a significant technical difference, but to me new and delete signal that an object is being created and destroyed, even if the object is just a character. When you allocate an array of characters as a generic "block," it uses the array allocator (specially suited to arrays) and notionally constructs characters in it. Then you must use placement new to construct a new object on top of those characters, which is essentially object aliasing or double construction, followed by double destruction when you want to delete everything.

    It's better to sidestep the C++ object model with malloc/free than to twist it to avoid dealing with data as objects.

    Oh, an alternative is to use a custom operator new, but it can be a can of worms so I do not recommend it.

    struct Hamburger {
      int tastyness;
    public:
      char *GetMeat();
      static void *operator new( size_t size_of_bread, size_t size_of_meat )
          { return malloc( size_of_bread + size_of_meat ); }
      static void operator delete( void *ptr )
          { free( ptr ); }
    };
    
    int main() {
        char const *hamburger_identity = "yum";
        size_t meat_size = strlen( hamburger_identity ) + 1;
        Hamburger *hamburger = new( meat_size ) Hamburger;
        strcpy( hamburger->GetMeat(), hamburger_identity );
        cout << hamburger->GetMeat() << '\n';
    }
    

提交回复
热议问题