这里有人用过c++的“placement new”吗?如果有,为什么?在我看来,它只在内存映射硬件上有用。


当前回答

我曾看到它被用作“动态类型”指针的轻微性能hack(在“引擎盖下”一节中):

但这是我用来获得小类型的快速性能的棘手技巧:如果所持有的值可以放入void*中,我实际上不需要分配一个新对象,而是使用placement new将其强制到指针本身。

其他回答

我使用它来构造通过alloca()分配到堆栈上的对象。

无耻的宣传:我在这里写过博客。

我们将它用于自定义内存池。简单介绍一下:

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

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

    static Pool *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, ...);

现在你可以将对象聚集在一个单独的内存区域中,选择一个非常快但不进行释放的分配器,使用内存映射,以及任何你希望通过选择池并将其作为参数传递给对象的放置new操作符来施加的语义。

在http://xll.codeplex.com上查看xll项目中的fp.h文件,它解决了喜欢随身携带维度的数组“与编译器的不必要的亲密关系”问题。

typedef struct _FP
{
    unsigned short int rows;
    unsigned short int columns;
    double array[1];        /* Actually, array[rows][columns] */
} FP;

我曾看到它被用作“动态类型”指针的轻微性能hack(在“引擎盖下”一节中):

但这是我用来获得小类型的快速性能的棘手技巧:如果所持有的值可以放入void*中,我实际上不需要分配一个新对象,而是使用placement new将其强制到指针本身。

一般来说,放置新是为了摆脱“正常新”的分配成本。

我使用它的另一个场景是,我想要访问一个仍待构造的对象的指针,以实现每个文档的单例。