“放置新的”有什么用处?

有没有人曾经使用过C ++的“放置新”? 如果是这样,为了什么? 它看起来像它只会在内存映射硬件上有用。


Placement new允许您在已经分配的内存上构建一个对象。

您可能希望这样做优化(不要一直重新分配会更快),但需要多次重新构建对象。 如果您需要继续重新分配,即使您不想使用它,分配的分配量也可能比您需要的分配效率更高。

Devex给出了一个很好的例子:

标准C ++还支持放置新操作符,它在预分配的缓冲区上构建一个对象。 这在构建内存池,垃圾回收器时或仅仅在性能和异常安全性至关重要时(这是没有分配失败的危险,因为内存已被分配,并且在预分配的缓冲区上构建对象需要更少的时间) :

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

您可能还想确保在关键代码的某个部分没有分配失败(例如,您可能在使用起搏器工作)。 在这种情况下,您会希望使用新的展示位置。

取消分配新的分配

您不应该释放每个使用内存缓冲区的对象。 相反,您应该只删除[]原始缓冲区。 您将不得不手动直接调用类的析构函数。 有关此方面的好建议,请参阅Stroustrup的常见问题解答:是否存在“展示位置删除”?


我们将它与自定义内存池一起使用。 只是一个草图:

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

现在,您可以将对象集中在一个内存区域中,通过选择池并将其作为参数传递给对象的位置,选择速度非常快但不释放的分配器,使用内存映射以及您希望实施的任何其他语义新运营商。


如果你想分配分配和初始化,这很有用。 STL使用placement new来创建容器元素。

链接地址: http://www.djcxy.com/p/14029.html

上一篇: What uses are there for "placement new"?

下一篇: Compile and run program without main() in C