正确分配一个新的放置数组

问题描述 投票:0回答:1

我正在构建一个内存分配器并使用placement new。假设我想将10个元素“放置”到堆上已分配的数组中。

第一个常规new在堆上分配必要数量的字节,然后我在适当的位置构造我的WE对象。

struct WE {
    WE() {
        std::cout << "WE default constructed\n";
    }
    ~WE() {
        std::cout << "WE default destructed\n";
    }

    double d;
    int i;
    char c;
};

以下使用的展示位置是否正确?

代码编译和输出似乎是正确的,但我有一些疑问。

// 1. allocate
const int elements = 10;
int nbytes = elements * sizeof(WE);
char* memory = new char[nbytes];
WE* pB = (WE*)memory;
int step = sizeof(WE);
// 2. construct
for (int i = 0; i < nbytes; i += step)
    new (pB + i) WE();
// 3. process
for (int i = 0; i < nbytes; i += step)
    pB[i].i = i * 2;
for (int i = 0; i < nbytes; i += step)
    std::cout << '[' << i << ']' << '=' << pB[i].i << '\n';
// 4. destruct
for (int i = 0; i < nbytes; i += step)
    pB[i].~WE();
// 5. deallocate
delete[] memory;
pB = nullptr;
memory = nullptr;

如果上面的问题一切都很好,那么请允许我添加一个问题,如何在任意字节边界上对齐此数组?说我想在sizeof(WE) 16(而不是alignof(WE),这是8)对齐。这种修改会不会:alignas(sizeof(WE)) char* memory = new char[nbytes];足以做到这一点?我也听说过std::aligned_storage。我不确定它是否能提供任何好处。 (如果第二个问题让你感到困惑,或者如果我在第1部分搞砸了,那就别忘了。)先谢谢。

c++ memory-management allocation memory-alignment placement-new
1个回答
1
投票

对于对象构造(placement new),您可以迭代字节/字符:

for (int i = 0; i < nbytes; i += step) new (memory + i) WE();

或元素:

for (int i = 0; i < elements; i++) new (pB + i) WE();

在您访问元素的其余循环中,您需要使用第二个选项。

至于对齐,动态内存分配返回一个在alignof(std::max_align_t)(C ++ 11)对齐的内存块。示例值为16(GCC / x86_64),这是您想要的,但标准当然不保证该值。

如果我没有错,那么在C ++ 17之前,operator new不能直接为过度对齐的对象分配内存,而std::aligned_storage在这里没有帮助。从C ++ 17开始,有一些特殊版本的operator new可以接受对齐信息,请参阅:https://en.cppreference.com/w/cpp/memory/new/operator_new

© www.soinside.com 2019 - 2024. All rights reserved.