gpt4 book ai didi

c++ - 可以以可移植方式使用新的数组放置吗?

转载 作者:IT老高 更新时间:2023-10-28 12:33:36 26 4
gpt4 key购买 nike

在将可移植代码用于数组时,是否可以实际使用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[] 返回的地址与我传入的地址相同。

最佳答案

就我个人而言,我会选择不在数组上使用新位置,而是在数组中的每个项目上单独使用新位置。例如:

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\n", pBuffer, pA);

// dont forget to destroy!
for(int i = 0; i < NUMELEMENTS; ++i)
{
pA[i].~A();
}

delete[] pBuffer;

return 0;
}

无论您使用哪种方法,请确保在删除 pBuffer 之前手动销毁数组中的每个项目,因为您最终可能会出现泄漏;)

注意:我还没有编译这个,但我认为它应该可以工作(我在一台没有安装 C++ 编译器的机器上)。它仍然表明了这一点:) 希望它在某种程度上有所帮助!


编辑:

它需要跟踪元素数量的原因是,它可以在您对数组调用 delete 时遍历它们,并确保在每个对象上调用析构函数。如果它不知道有多少,它就无法做到这一点。

关于c++ - 可以以可移植方式使用新的数组放置吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15254/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com