3

I have a class A. Some library I am using allocates a given amount of memory for me, sizeof A, and returns a void pointer to it.

A* pObj = (A*) some_allocator_im_forced_to_use( sizeof A );

Now how can I create a new instance of A, in the memory that just got allocated?

I have tried it with:

*pObj = A();

But this didn't work - the destructor got called right after the constructor of A.

Sogu
  • 31
  • 1

6 Answers6

8

You can use placement new:

A* pObj = new ( some_allocator_im_forced_to_use( sizeof( A ) ) ) A;

This constructs a new A instance at the location returned by the function some_allocator_im_forced_to_use. This function needs to return a void* pointing to sufficient memory appropriately aligned for an A object on the implementation in question.

It is likely that you'll have to manually call the destructor for this object manually as you won't be able to use the usual delete pObj to destroy it.

pObj->~A();
// Call custom allocator's corresponding deallocation function on (void*)pObj

In order to correctly destroy the object and release the memory you might consider using a shared_ptr with a custom deleter.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
3

Use placement new:

new (pObj) A;

You will also need to destroy the object differently, since delete assumes (incorrectly) that you created the object with plain old new:

pObj->~A();
some_deallocator_im_forced_to_use( pObj );
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
2

You need 'placement new'

See this answer: What uses are there for "placement new"?

Community
  • 1
  • 1
bgporter
  • 35,114
  • 8
  • 59
  • 65
1

Placement new.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
1

Some people have advocated placement new.

That's dangerous, and the so far two usage examples have omitted crucial details like including the <new> header, qualifying the call like ::new ..., and how to clean up.

The safe solution is to define custom allocation and deallocation functions for your class, or for a class derived from your class. The example below shows the latter. Note that the virtual destructor is only there to support the class derivation; if you don't derive, you don't need it.

#include <stddef.h>
#include <iostream>

void* some_allocator_im_forced_to_use( size_t size )
{
    std::cout << "Allocated " << size << " bytes." << std::endl;
    return ::operator new( size );
}

void some_deallocator_im_forced_to_use( void* p, size_t size )
{
    std::cout << "Deallocated " << size << " bytes." << std::endl;
    ::operator delete( p );
}

struct A
{
    int x_;
    A(): x_( 42 ) {}
    virtual ~A() {}
};

struct CustomAllocedA
    : A
{
    void* operator new( size_t size )
    {
        return some_allocator_im_forced_to_use( size );
    }

    void operator delete( void* p, size_t size )
    {
        some_deallocator_im_forced_to_use( p, size );
    }
};

int main()
{
    A* const    p    = new CustomAllocedA;

    std::cout << p->x_ << std::endl;
    delete p;
}

Important: although this is "safe" in itself, and although this particular example is safe, the safety for your code ultimately rests on your custom allocator returning a pointer to properly aligned memory.

Cheers & hth.,

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
0

If your allocator follows the model of std::allocator it shall have several methods:

  • allocate
  • construct
  • destroy
  • deallocate

They are pretty much self-explanatory, what is important is that you are responsible for calling them:

  • in the right order
  • and not forgetting any

or you'll either get UB or a leak.

However I am somewhat surprise that only the size is required by your allocator, normally it shall also requires the alignment of the object, unless is simply uses the maximum alignment possible on the target regardless of the object to be allocated.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722