为了账号安全,请及时绑定邮箱和手机立即绑定

可以以可移植的方式使用阵列的新放置吗?

可以以可移植的方式使用阵列的新放置吗?

慕侠2389804 2019-12-15 11:12:22
将其用于数组时,是否可以实际利用可移植代码中的新放置?从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大,因此数组中的最后一个元素将写入未分配的堆中。因此,问题是您能找出为了安全地使用位置new []而实现需要多少额外开销?理想情况下,我需要一种可在不同编译器之间移植的技术。请注意,至少在VC的情况下,不同类的开销似乎有所不同。例如,如果我在示例中删除了虚拟析构函数,则new []返回的地址与我传入的地址相同。
查看完整描述

3 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

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


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并确保在每个对象上都调用了析构函数时,它可以遍历它们。如果不知道有多少个,它将无法执行此操作。



查看完整回答
反对 回复 2019-12-16
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

5.3.4的第12节讨论了数组分配的开销,除非我误读了它,否则似乎暗示我编译器也可以将其添加到new位置上:


此开销可能会应用于所有数组new-expression,包括引用库函数operator new [](std :: size_t,void *)和其他布局分配函数的那些表达式。开销量可能从一个新调用到另一个调用而有所不同。


就是说,我认为VC是唯一给我带来麻烦的编译器,其中包括GCC,Codewarrior和ProDG。不过,我必须再次检查以确保。



查看完整回答
反对 回复 2019-12-16
?
千万里不及你

TA贡献1784条经验 获得超9个赞

Placement new本身是可移植的,但是您对它对指定内存块所做的假设不是可移植的。就像之前所说的,如果您是一个编译器并且被分配了一块内存,那么如果您拥有的只是一个指针,您如何知道如何分配一个数组并正确地破坏每个元素?(请参阅运算符delete []的界面。)

编辑:

实际上存在一个放置删除,只有在构造函数使用放置位置new []分配数组时构造函数引发异常时才调用它。

new []是否实际上需要以某种方式跟踪元素的数量,这取决于标准,由标准决定。不幸的是,在这种情况下。



查看完整回答
反对 回复 2019-12-16
  • 3 回答
  • 0 关注
  • 188 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信