看起来,placement new
在预分配的内存上创建了一个新对象,它是否意味着需要更少的时间?看起来比使用旧的普通new
分配更快。那么,如果这样方便快捷,为什么不一直使用placement new
?
答案 0 :(得分:4)
new
基本上等同于做
T* ptr = static_cast<T*>(malloc(sizeof(T)));
new(ptr) T;
当然,由于错误检查等原因,实际情况看起来有点不同,但结果大致相同(通过不完全相同,你可以delete
指定这样的指针,而不是你需要明确地调用析构函数(ptr->~T()
),然后使用free
释放内存。
因此,新的放置应该比非放置新的更快,因为它不需要分配内存。但问题是内存需要在某处分配。因此,您实际上已经通过调用new
替换了对placement new
的一个调用,并在某处调用了一些代码(如果不是,为什么不首先使用new
?)。很明显,这样不太方便,容易出错。
现在当然你可以编写一个更快的分配方法,但为此你通常需要做一些权衡。编写一个分配器并不容易,如果不使用更多的内存(额外的数据可以更快地识别空闲块)或者使其非常具体(编写单个对象的快速分配比使用它更容易)一般的)。最后,通常不值得付出努力(对于可能已经完成的努力值得花钱的情况,所以你可以使用现有的分配器(可能在内部使用放置新的))。
当然有新的放置用途(有时你确实预先分配了内存),但这不是常见的情况
答案 1 :(得分:3)
对于大多数程序来说,这是不必要的,因为它们的使用模式并不是必需的。对于那些不使用堆的程序来说没有区别,而且很难做到正确(比你的操作系统更好)。您也可以通过优化分配获得如此多的收益。在大多数情况下,任何算法优化都将导致更大的总体加速。通常不需要定制分配器可以提供的许多保证(通过预分配的内存分配的保证时间限制,低内存碎片)。
有些程序可以从内存管理中受益,但它们很难识别。在您发现内存分配实际上是瓶颈之后,找到更好的分配方案就更难了。当一切都完成后,仍然不值得麻烦。
答案 2 :(得分:2)
放置new的目的之一是使用自定义分配器来创建新对象,并调用它们的构造函数。它并不总是更快,因为它只有你的自定义分配器一样快。
答案 3 :(得分:2)
用于将对象放置在内存中特定位置的新位置可能会花费更少的时间,因为您实际上避免在此步骤分配内存。
但是,它必须在某个时间点分配,之前可能需要时间。 如果你真的有理由将对象放在预分配的内存中,那么使用它是有意义的。
这种 new 运算符不是单独使用的。更多详情here。
另外,请记住placement new不会自动调用析构函数!
您必须手动为foo->~Foo();
执行Foo foo;
。
答案 4 :(得分:1)
我发现放置new的唯一地方会使你的分配速度明显加快,那就是你有大量相同大小的对象,这些对象的生命周期有限,导致它们被频繁地分配和销毁。如果你不能保证这种行为,你可能最好使用默认的新实现。
答案 5 :(得分:1)
需要大量相同大小对象的应用程序通常可以从池(或批量)分配中看到主要的加速。基本上,您为该对象的大量分配一个大缓冲区(或页面),然后在请求该对象时调用其中的placement new。虽然这可以加快速度,但对大多数程序来说并不是必需的。
尝试为不需要它的程序执行此操作可能只会为您提供最低的加速,但可能会花费您大量的时间进行调试。
所以真的看看你需要什么;如果您要分配大量相同的对象,是的,新位置可能会更快。但只是几个对象?我不打扰。
但这并不总是时间问题。例如,您可以使用placement new来保证对象在堆上的对齐。你可以这样做:
void* buffer = aligned_malloc(sizeof(Object), 16);
Object* object = new (buffer) Waypoint();
这对某些类型是必要的,例如浮点数组与SSE函数和寄存器一起使用。