views:

5856

answers:

14

Has anyone here ever used C++'s "placement new"? If so, what for? It looks to me like it would only be useful on memory-mapped hardware.

+2  A: 

It is useful if you are building a kernel - where do you place the kernel code you read from disk or the pagetable? You need to know where to jump to.

Or in other, very rare circumstances such as when you have loads of allocated room and want to place a few structures behind each other. They can be packed this way without the need for the offsetof() operator. There are other tricks for that too, though.

I also believe some STL implementations make use of placement new, like std::vector. They allocate room for 2^n elements that way and don't need to always realloc.

mstrobl
Reducing memory allocations is one primary reason to use it, as well as "tricks" like loading objects off of disk
lefticus
I don't know of any kernels written in C++; most kernels are written in straight C.
Adam Rosenfield
The operating system with which I learned OS basics is written in C++: http://sweb.sourceforge.net
mstrobl
+1  A: 

I've used it for storing objects with memory mapped files.
The specific example was an image database which processed vey large numbers of large images (more than could fit in memory).

Martin Beckett
+11  A: 

It's useful if you want to separate allocation from initialization. STL uses placement new to create container elements.

MSN

MSN
A: 

It's used by std::vector<> since std::vector likes to allocate more memory than there are objects in the vector.

Andreas Magnusson
+24  A: 

Placement new allows you to construct an object on memory that's already allocated.

You may want to do this for optimizations (it is faster not to re-allocate all the time) but you need to re-construct an object multiple times. If you need to keep re-allocating it might be more efficient to allocate more than you need, even know you don't want to use it yet.

devex gives a good example:

Standard C++ also supports placement new operator, which constructs an object on a pre-allocated buffer. This is useful when building a memory pool, a garbage collector or simply when performance and exception safety are paramount (there's no danger of allocation failure since the memory has already been allocated, and constructing an object on a pre-allocated buffer takes less time):

void placement() {

char *buf  = new char[1000];   //pre-allocated buffer
    string *p = new (buf) string("hi");  //placement new
    string *q = new string("hi");  //ordinary heap allocation

You may also want to be sure there can be no allocation failure at a certain part of critical code (maybe you work on a pacemaker for example). In that case you would want to use placement new.

Deallocation in placement new:

You should not deallocate every object that is using the memory buffer. Instead you should delete[] only the original buffer. You would have to then call the destructors directly of your classes manually. For a good suggestion on this please see Stroustrup's FAQ on: Is there a "placement delete"?

Brian R. Bondy
But I would add that generally it's considered obsolete. As far as I know, it hasn't been deprecated because there are good uses for placement new.
Max Lybbert
It's not deprecated as you need this feature to effeciently implement container objects (like vector). If you are not building your own container you don't need to use this feature though.
Martin York
Well, there are a number of possible uses, such as when deserialising parametric, immutable datatypes.
Marcin
Ya I think definitely not deprecated.
Brian R. Bondy
It is also very important to remember to #include <memory>, otherwise you might run into some terrible headaches in some platforms that do not automatically recognize placement new
Ramon Zarazua
Strictly, it's undefined behaviour to call `delete[]` on the original `char` buffer. Using placement `new` has ended the lifetime of the original `char` objects by re-using their storage. If you now call `delete[] buf` the dynamic type of the object(s) pointed to no longer matches their static type so you have undefined behaviour. It is more consistent to use `operator new`/`operator delete` to allocate raw memory inteded for use by placement `new`.
Charles Bailey
What is really useless is allocating arrays with placement syntax, see http://stackoverflow.com/questions/15254/can-placement-new-for-arrays-be-used-in-a-portable-way
mlvljr
It is beneficial to distinguish between operator new() and new() operator. the former allocates, while the latter constructs.
Comptrol
+7  A: 

I've used it to construct objects allocated on the stack via alloca().

shameless plug: I blogged about it here.

Ferruccio
Nice blog entry on the topic, thanks.
Head Geek
Very cool, you don't treat alloca failing though.
Motti
+7  A: 

We use it with custom memory pools. Just a sketch:

class Pool {
public:
    Pool() { /* implementation details irrelevant */ };
    virtual ~Pool() { /* ditto */ };

    virtual void *allocate(size_t);
    virtual void deallocate(void *);

    static Pool::misc_pool() { return misc_pool_p; /* global MiscPool for general use */ }
};

class ClusterPool : public Pool { /* ... */ };
class FastPool : public Pool { /* ... */ };
class MapPool : public Pool { /* ... */ };
class MiscPool : public Pool { /* ... */ };

// elsewhere...

void *pnew_new(size_t size)
{
   return Pool::misc_pool()->allocate(size);
}

void *pnew_new(size_t size, Pool *pool_p)
{
   if (!pool_p) {
      return Pool::misc_pool()->allocate(size);
   }
   else {
      return pool_p->allocate(size);
   }
}

void pnew_delete(void *p)
{
   Pool *hp = Pool::find_pool(p);
   // note: if p == 0, then Pool::find_pool(p) will return 0.
   if (hp) {
      hp->deallocate(p);
   }
}

// elsewhere...

class Obj {
public:
   // misc ctors, dtors, etc.

   // just a sampling of new/del operators
   void *operator new(size_t s)             { return pnew_new(s); }
   void *operator new(size_t s, Pool *hp)   { return pnew_new(s, hp); }
   void operator delete(void *dp)           { pnew_delete(dp); }
   void operator delete(void *dp, Pool*)    { pnew_delete(dp); }

   void *operator new[](size_t s)           { return pnew_new(s); }
   void *operator new[](size_t s, Pool* hp) { return pnew_new(s, hp); }
   void operator delete[](void *dp)         { pnew_delete(dp); }
   void operator delete[](void *dp, Pool*)  { pnew_delete(dp); }
};

// elsewhere...

ClusterPool *cp = new ClusterPool(arg1, arg2, ...);

Obj *new_obj = new (cp) Obj(arg_a, arg_b, ...);

Now you can cluster objects together in a single memory arena, select an allocator which is very fast but does no deallocation, use memory mapping, and any other semantic you wish to impose by choosing the pool and passing it as an argument to an object's placement new operator.

Don Wakefield
+2  A: 

I've used it to create objects based on memory containing messages received from the network.

Steve Fallows
+2  A: 

Generally, placement new is used to get rid of allocation cost of a 'normal new'.

Another scenario where I used it is a place where I wanted to have access to the pointer to an object that was still to be constructed, to implement a per-document singleton.

xtofl
+4  A: 

I've used it in realtime programming. We typically don't want to perform any dynamic allocation (or deallocation) after the system starts up, because there's no guarantee how long that is going to take.

What I can do is preallocate a large chunk of memory (large enough to hold any amount of whatever that the class may require). Then, once I figure out at runtime how to construct the things, placement new can be used to construct objects right where I want them. One situation I know I used it in was to help create a hetrogenious circular buffer.

It's certianly not for the feint of heart, but that's why they make the syntax for it kinda gnarly.

T.E.D.
Hi TED, could you please share more about the solution you have. I'm thinking on a pre-allocated solution but have not got much progress. Thank you in advance!
Viet
Well, the actual hetrogenious circular buffer code was really the tricky part to get right. The palcement new looks a little grisly, but by comparison it was no trouble at all.
T.E.D.
+1  A: 

The one place I've run across it is in containers which allocate a contiguous buffer and then fill it with objects as required. As mentioned, std::vector might do this, and I know some versions of MFC CArray and/or CList did this (because that's where I first ran across it). The buffer over-allocation method is a very useful optimization, and placement new is pretty much the only way to construct objects in that scenario. It is also used sometimes to construct objects in memory blocks allocated outside of your direct code.

I have used it in a similar capacity, although it doesn't come up often. It's a useful tool for the C++ toolbox, though.

Nick
+2  A: 

I've seen it used as a slight performance hack for a "dynamic type" pointer (in the section "Under the Hood"):

But here is the tricky trick I used to get fast performance for small types: if the value being held can fit inside of a void*, I don't actually bother allocating a new object, I force it into the pointer itself using placement new.

Max Lybbert
+1  A: 

Script engines can use it in the native interface to allocate native objects from scripts. See Angelscript (www.angelcode.com/angelscript) for examples.

Raindog
+2  A: 

Head Geek: BINGO! You got it totally - that's exactly what it's perfect for. In many embedded environments, external constraints and/or the overall use scenario forces the programmer to separate the allocation of an object from its initialization. Lumped together, C++ calls this "instantiation"; but whenever the constructor's action must be explicitly invoked WITHOUT dynamic or automatic allocation, placement new is the way to do it. It's also the perfect way to locate a global C++ object that is pinned to the address of a hardware component (memory-mapped I/O), or for any static object that, for whatever reason, must reside at a fixed address.

dorcsssc