当我们在处理数组时,是否有可能在可移植的代码中实际使用placement new呢?
看起来从new[]返回的指针并不总是与传入的地址相同(标准中的5.3.4, 注意12似乎确认了这一点),但我不知道如果情况是如此,如何为数组分配缓冲区。
以下示例展示了这个问题。在Visual Studio中编译,此示例将导致内存损坏:
#include <new>
#include <stdio.h>
class A
{
public:
A() : data(0) {}
virtual ~A() {}
int data;
};
int main()
{
const int NUMELEMENTS=20;
char *pBuffer = new char[NUMELEMENTS*sizeof(A)];
A *pA = new(pBuffer) A[NUMELEMENTS];
// With VC++, pA will be four bytes higher than pBuffer
printf("Buffer address: %x, Array address: %x\n", pBuffer, pA);
// Debug runtime will assert here due to heap corruption
delete[] pBuffer;
return 0;
}
看着内存,编译器似乎使用缓冲区的前四个字节来存储其中项的数量计数。这意味着,因为缓冲区大小仅为sizeof(A)*NUMELEMENTS
,数组中的最后一个元素被写入未分配的堆。
因此,问题在于您能否找出实现安全使用placement new[]所需的额外开销。理想情况下,我需要一种可在不同编译器之间移植的技术。请注意,至少在VC的情况下,开销似乎因不同类而异。例如,如果我从示例中删除虚析构函数,则从new[]返回的地址与我传递的地址相同。