views:

800

answers:

4

Is it possible in C++ to create a new object at a specific memory location? I have a block of shared memory in which I would like to create an object. Is this possible?

+30  A: 

You want placement new(). It basically calls the constructor using a block of existing memory instead of allocating new memory from the heap.

Edit: make sure that you understand the note about being responsible for calling the destructor explicitly for objects created using placement new() before you use it!

D.Shawley
Thanks for a good answer to a good question. I learned something new today. I would have ended up fanangling C constructs into cpp world to accomplish this.
San Jacinto
Thank you so much for your help. I googled for quite a while and never came across this.Thanks
Chris
+1 for specifying that the Destructor has to be called explicitly, normally you don't care but when its has side effects besides releasing memory...
Matthieu M.
I highly recommend reading **all** of Marshall Cline's C++ FAQ Lite several times. It is an invaluable resource.
D.Shawley
Unfortunately the articile you point it is flawed and wrong. Using a char array like that is not a good idea. The problem is that an array declared like that has no guaranteed alignment. What you need to do is use a vector<char> Because the memory is dynamically allocated the memory will be correclty aliagened (iff the space allocated is equal to or larger than the size of the object (Check out the alighment properties for new in the standard))
Martin York
@Martin: interesting point... I'll have to dig into that one. Interestingly enough, the Standard uses the same example in clause 4 of 18.4.1.3. Then again, the example in the Standard lacks the necessary cast to `void*`... oh well.
D.Shawley
@D.Shawley: I highly recommend not reading the FAQ to seriously. It is serioulsy flawed in many places, and often disagrees with commonly accepted best practices as espoused by Sutter/Alexan­dres­cu and Meyers.
Martin York
@Martin: Your comment about alignment is already noted in that FAQ, albeit without the mention of std::vector.
JAB
@JAB: That's new. Rather than say it is dangerous why not describe a method that is guaranteed to work! The solution is just as simple as the version in the FAQ (as it is really really easy (use dynamic memory (A vector just being an example)).
Martin York
+3  A: 

Yes. You need to use placement variant of operator new(). For example:

void *pData = ....; // memory segment having enough space to store A object
A *pA = new (pData) A;

Please note that placement new does not throw exception.

dimba
+1  A: 

Unfortunately the artivle on c++-faq-lite is BAD.

You need to this:

class Plop { /* STUFF */ };


std::vector<char>    buffer(sizeof(Plop));
Plop* p = new (&buffer[0]) Plop(1);

// Do Stuff

p->~Plop();

Advantages of this technique.

  • The buffer memory will be reclaimed by RAII when vector is out of scope.
  • The memory allocated by buffer is guranteed to be correctly aligned.
    • This is guranteed by the standard.
      This is because std::vector<> uses new to dynamically allocate the buffer.
    • The common anti usage is to use a locally declared char[] array.
      The problem with this is that the array has no guarantted alignement properties.
      This has a tendency to cause crashes when you least expect them and is impossable to debug.
Martin York
No, you don't "need" to do this. Using `malloc()/free()` is a perfectly fine alternative that provides the same alignment guarantees, it just doesn't provide RAII.
Adam Rosenfield
malloc/free provides the same type of gurantees as new/delete yes. If I was going to use malloc/free I may as well use new[]/delete[]. But std::vector does that automatically. So I am a just using std::vector as an exception safe surrage for new[]/delete[].
Martin York
+1  A: 

if you want to allocate a lot of fine-grained objects, the best approach will be to use placement new in conjunction with some sort of a ring buffer. otherwise, you will have to keep track of the pointers aside from the object pointers themselves.

geva30