Can placement new for arrays be used in a portable way?将其用于数组时,是否可以实际使用可移植代码中的新放置? 从new []返回的指针似乎并不总是与您传递的地址相同(5.3.4,标准中的注释12似乎确认这是正确的),但是我看不到您如何在这种情况下,可以为数组分配一个缓冲区。 以下示例显示了该问题。与Visual Studio一起编译,此示例导致内存损坏:
看着内存,编译器似乎正在使用缓冲区的前四个字节来存储其中的项目数计数。这意味着,由于缓冲区只有 因此,问题是您能找出为了安全地使用位置new []而实现需要多少额外开销?理想情况下,我需要一种可在不同编译器之间移植的技术。请注意,至少在VC的情况下,不同类的开销似乎有所不同。例如,如果我在示例中删除了虚拟析构函数,则new []返回的地址与我传入的地址相同。 就我个人而言,我可以选择不在数组上使用新的展示位置,而是在数组中的每个项目上单独使用新的展示位置。例如:
不管使用哪种方法,请确保在删除pBuffer之前手动销毁数组中的每个项,否则可能会导致泄漏;) 注意:我还没有编译它,但是我认为它应该可以工作(我在没有安装C ++编译器的机器上)。它仍然表明要点:)希望它能以某种方式有所帮助! 编辑: 它需要跟踪元素数量的原因是,以便当您在数组上调用delete并确保在每个对象上都调用了析构函数时,它可以遍历它们。如果不知道有多少个,它将无法执行此操作。 @Derek 5.3.4的第12节讨论了数组分配的开销,除非我误读了它,否则似乎暗示我编译器也可以将其添加到new放置上是有效的:
就是说,我认为VC是唯一给我带来麻烦的编译器,其中包括GCC,Codewarrior和ProDG。不过,我必须再次检查以确保。 放置新自身本身是可移植的,但是您对它对指定内存块所做的假设均不可移植。就像之前所说的,如果您是一个编译器并被分配了一块内存,那么如果您拥有的只是一个指针,您如何知道如何分配一个数组并正确地破坏每个元素? (请参阅操作员delete []的界面。) 编辑: 实际上有一个放置删除,只有在构造函数使用放置位置new []分配数组时构造函数引发异常时才调用它。 new []是否实际上需要以某种方式跟踪元素的数量,这取决于标准,由标准决定。不幸的是,在这种情况下。 @詹姆士
经过考虑后,我同意你的看法。没有新的放置位置需要存储元素数量的原因,因为没有放置位置删除。由于没有删除放置,因此没有理由放置新的存储元素的数量。 我还在Mac上使用带有析构函数的类在gcc上对其进行了测试。在我的系统上,new放置没有更改指针。这使我想知道这是否是VC ++问题,以及是否可能违反该标准(据我所知,该标准并未专门解决此问题)。 感谢您的答复。当我遇到这个问题时,我最终使用的解决方案是为数组中的每个项目使用new布局(对不起,应该在问题中提到)。我只是觉得使用new []放置它肯定缺少一些东西。实际上,由于标准允许编译器向数组添加额外的未指定开销,因此似乎无法使用new []放置。我看不到如何安全,便携地使用它。 我什至还不清楚为什么它需要额外的数据,因为无论如何您都不会在数组上调用delete [],所以我不完全明白为什么它需要知道其中有多少个项目。 与使用单个元素计算一个新放置的大小的方法类似,使用这些元素的数组计算一个数组所需的大小。 如果在其他计算中需要大小,而元素数量未知,则可以使用sizeof(A [1])乘以所需的元素数。 例如
我认为gcc与MSVC的作用相同,但是当然这并不能使其"可移植"。 我认为当NUMELEMENTS确实是一个编译时间常数时,您可以解决该问题,如下所示:
A* p = new (buffer) Arr; 这应该使用新的标量放置。 |