首页 > 后端开发 > C++ > 正文

数组的放置新功能在 C 中真的可以移植吗?

Mary-Kate Olsen
发布: 2024-11-15 04:05:02
原创
533 人浏览过

Is Placement New for Arrays Truly Portable in C  ?

数组的新放置:可移植性问题

在 C 中,新放置允许在指定地址分配内存。然而,它在阵列中的使用带来了可移植性的挑战。本文探讨了这个问题并提出了一个可移植的解决方案。

通常假设 new[] 返回的指针与提供的地址一致。然而,C 标准(5.3.4,注释 12)表明情况可能并非如此。当尝试使用放置 new 为数组分配缓冲区时,这会带来问题。

以下代码演示了此问题:

#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];

    printf("Buffer address: %x, Array address: %x\n", pBuffer, pA);

    delete[] pBuffer; // Assertion failure due to heap corruption

    return 0;
}
登录后复制

对内存的检查表明,某些编译器(例如, Visual Studio)在数组之前分配额外的字节以进行内部簿记(例如,数组元素的计数)。这可能会导致堆损坏。

问题出现了:我们能否确定与不同编译器的数组的放置 new 相关的开销?我们的目标是找到一个可移植的解决方案。

建议的解决方案

与其在整个数组上使用placement 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);

  // Manual destruction
  for (int i = 0; i < NUMELEMENTS; ++i) {
    pA[i].~A();
  }

  delete[] pBuffer;

  return 0;
}
登录后复制

此方法显式控制数组中每个对象的放置,并确保正确执行销毁。

结论

使用放置new 数组需要仔细考虑编译器特定的开销。所提出的解决方案通过单独分配和销毁数组元素提供了一种可移植的替代方案。

以上是数组的放置新功能在 C 中真的可以移植吗?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板