首页  >  文章  >  后端开发  >  在 C 数组上使用布局是可移植的新功能吗?

在 C 数组上使用布局是可移植的新功能吗?

DDD
DDD原创
2024-11-18 05:38:02628浏览

Is Using Placement New on C   Arrays Portable?

数组的可移植放置新功能

标准库的放置新运算符允许在指定地址分配内存。然而,由于返回的指针和传入的地址之间可能存在差异,它与数组一起使用会引起对可移植性的担忧。

理解问题

当使用placement new时数组,返回的指针可能与提供的地址不一致。 C 标准 5.3.4 的注释 12 对此进行了解释。因此,专门为数组分配缓冲区会出现问题。

请考虑以下示例:

#include <iostream>
#include <new>

class A {
public:
    A() : data(0) {}
    ~A() {}
    int data;
};

int main() {
    const int NUMELEMENTS = 20;

    char *pBuffer = new char[NUMELEMENTS * sizeof(A)];
    A *pA = new(pBuffer) A[NUMELEMENTS];

    // Output may show pA as four bytes higher than pBuffer
    std::cout << "Buffer address: " << pBuffer << ", Array address: " << pA << std::endl;

    delete[] pBuffer;

    return 0;
}

此示例通常会导致 Microsoft Visual Studio 下的内存损坏。对内存的检查表明,编译器在数组分配前添加了四个字节,可能存储数组元素的计数。此行为因所使用的编译器和类而异。

可移植解决方案

要解决此可移植性问题,请避免直接在数组上使用放置 new。相反,请考虑使用放置 new 单独分配数组的每个元素:

#include <iostream>
#include <new>

class A {
public:
    A() : data(0) {}
    ~A() {}
    int data;
};

int main() {
    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();
    }

    std::cout << "Buffer address: " << pBuffer << ", Array address: " << pA << std::endl;

    // Remember to manually destroy each element
    for (int i = 0; i < NUMELEMENTS; ++i) {
        pA[i].~A();
    }

    delete[] pBuffer;

    return 0;
}

无论采用哪种方法,在删除缓冲区之前手动销毁每个数组元素对于防止内存泄漏至关重要。

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

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn