What are uses of the C++ construct “placement new”

2019-01-14 03:28发布

I just learned about the C++ construct called "placement new". It allows you to exactly control where a pointer points to in memory. It looks like this:

 #include <new>        // Must #include this to use "placement new"
 #include "Fred.h"     // Declaration of class Fred

 void someCode()
 {
   char memory[sizeof(Fred)];
   void* place = memory;

   Fred* f = new(place) Fred();   // Create a pointer to a Fred(),
                                  // stored at "place"

   // The pointers f and place will be equal

   ...
 } 

(example from C++ FAQ Lite)

In this example, the this pointer of Fred will be equal to place.


I've seen it used in our team's code once or twice. In your experience, what does this construct enable? Do other pointer languages have similar constructs? To me, it seems reminiscent of equivalence in FORTRAN, which allows disparate variables to occupy the same location in memory.

12条回答
劫难
2楼-- · 2019-01-14 04:05

By controlling the exact placement, you can align things in memory and this can sometimes be used to improve CPU fetch/cache performance. Never actually saw it in use, though

查看更多
Bombasti
3楼-- · 2019-01-14 04:08

It is also used for embedded programming, where IO devices are often mapped to specific memory addresses

查看更多
走好不送
4楼-- · 2019-01-14 04:12

It allows you to do your own memory management. Usually this will get you at best marginally improved performance, but sometimes it's a big win. For example, if your program is using a large number of standard-sized objects, you might well want to make a pool with one large memory allocation.

This sort of thing was also done in C, but since there are no constructors in C it didn't require any language support.

查看更多
Juvenile、少年°
5楼-- · 2019-01-14 04:12

Its usefull when building your own container like objects.

For example if you were to create a vector. If you reserve space for a large number of objects you want to allocate the memory with some method that does not invoke the constructor of the object (like new char[sizeof(object) * reserveSize]). Then when people start adding objects into the vector you use placement new to copy them into allocated memory.

template<typename T>
class SillyVectorExample
{
    public:
        SillyVectorExample()
            :reserved(10)
            ,size(0)
            ,data(new char[sizeof(T) * reserved])
        {}
        void push_back(T const& object)
        {
            if (size >= reserved)
            {
                // Do Somthing.
            }
            // Place a copy of the object into the data store.
            new (data+(sizeof(T)*size))  T(object);
            ++size;
        }
        // Add other methods to make sure data is copied and dealllocated correctly.
    private:
        size_t   reserved;
        size_t   size;
        char*    data;
 };

PS. I am not advocating doing this. This is just a simplified example of how containers can work.

查看更多
Evening l夕情丶
6楼-- · 2019-01-14 04:15

I've used it when constructing objects in a shared memory segment.

查看更多
Rolldiameter
7楼-- · 2019-01-14 04:20

Placement new is NOT about making pointers equal (you can just use assignment for that!).

Placement new is for constructing an object at a particular location. There are three ways of constructing an object in C++, and placement new is the only one that gives you explicit control over where that object "lives". This is useful for several things, including shared memory, low-level device I/O, and memory pool/allocator implementation.

With stack allocation, the object is constructed at the top of the stack, wherever that happens to be currently.

With "regular" new, the object is constructed at an effectively arbitrary address on the heap, as managed by the standard library (unless you've overridden operator new).

Placement new says "build me an object at this address specifically", and its implementation is simply an overload of operator new that returns the pointer passed to it, as a means of getting to the remainder of the machinery of the new operator, which constructs an object in the memory returned by the operator new function.

It's also worth noting that the operator new function can be overloaded with arbitrary arguments (just as any other function). These other arguments are passed via the "new(arg 2, arg3, ..., argN)" syntax. Arg1 is always implicitly passed as "sizeof(whatever you're constructing)".

查看更多
登录 后发表回答