可以以便携式方式使用新的数组放置吗?
在将可移植代码用于数组时,是否可以实际使用placement new?
Is it possible to actually make use of placement new in portable code when using it for arrays?
您从 new[] 返回的指针似乎与您传入的地址并不总是相同(5.3.4,标准中的注释 12 似乎确认这是正确的),但我不如果是这种情况,看看如何为数组分配一个缓冲区.
It appears that the pointer you get back from new[] is not always the same as the address you pass in (5.3.4, note 12 in the standard seems to confirm that this is correct), but I don't see how you can allocate a buffer for the array to go in if this is the case.
以下示例显示了该问题.此示例使用 Visual Studio 编译,导致内存损坏:
The following example shows the problem. Compiled with Visual Studio, this example results in memory corruption:
#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
", pBuffer, pA);
// Debug runtime will assert here due to heap corruption
delete[] pBuffer;
return 0;
}
查看内存,编译器似乎正在使用缓冲区的前四个字节来存储其中项目数的计数.这意味着因为缓冲区只有 sizeof(A)*NUMELEMENTS
大,所以数组中的最后一个元素被写入未分配的堆中.
Looking at the memory, the compiler seems to be using the first four bytes of the buffer to store a count of the number of items in it. This means that because the buffer is only sizeof(A)*NUMELEMENTS
big, the last element in the array is written into unallocated heap.
所以问题是,您能否找出您的实现需要多少额外开销才能安全地使用placement new[]?理想情况下,我需要一种在不同编译器之间可移植的技术.请注意,至少在 VC 的情况下,不同类的开销似乎不同.例如,如果我在示例中删除虚拟析构函数,则 new[] 返回的地址与我传入的地址相同.
So the question is can you find out how much additional overhead your implementation wants in order to use placement new[] safely? Ideally, I need a technique that's portable between different compilers. Note that, at least in VC's case, the overhead seems to differ for different classes. For instance, if I remove the virtual destructor in the example, the address returned from new[] is the same as the address I pass in.
推荐答案
我个人会选择不在数组上使用新的位置,而是在数组中的每个项目上单独使用新的位置.例如:
Personally I'd go with the option of not using placement new on the array and instead use placement new on each item in the array individually. For example:
int main(int argc, char* argv[])
{
const int NUMELEMENTS=20;
char *pBuffer = new char[NUMELEMENTS*sizeof(A)];
A *pA = (A*)pBuffer;
for(int i = 0; i < NUMELEMENTS; ++i)
{
pA[i] = new (pA + i) A();
}
printf("Buffer address: %x, Array address: %x
", pBuffer, pA);
// dont forget to destroy!
for(int i = 0; i < NUMELEMENTS; ++i)
{
pA[i].~A();
}
delete[] pBuffer;
return 0;
}
无论您使用哪种方法,请确保在删除 pBuffer 之前手动销毁数组中的每个项目,因为您最终可能会出现泄漏;)
Regardless of the method you use, make sure you manually destroy each of those items in the array before you delete pBuffer, as you could end up with leaks ;)
注意:我还没有编译这个,但我认为它应该可以工作(我在一台没有安装 C++ 编译器的机器上).它仍然表明了这一点:) 希望它在某种程度上有所帮助!
Note: I haven't compiled this, but I think it should work (I'm on a machine that doesn't have a C++ compiler installed). It still indicates the point :) Hope it helps in some way!
它需要跟踪元素数量的原因是,它可以在您对数组调用 delete 时遍历它们,并确保在每个对象上调用析构函数.如果它不知道有多少,它就无法做到这一点.
The reason it needs to keep track of the number of elements is so that it can iterate through them when you call delete on the array and make sure the destructors are called on each of the objects. If it doesn't know how many there are it wouldn't be able to do this.
相关文章