【问题标题】:Properly allocate an array with placement new正确分配带有新位置的数组
【发布时间】:2018-09-05 12:08:32
【问题描述】:

我正在构建一个内存分配器并使用新的放置。 假设我想将 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;
};

以下对placement new 的用法是否正确?

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

// 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 部分搞砸了,请忘记它。)提前致谢。

【问题讨论】:

  • 所有for 循环都是错误的,pB + iWE* 类型的指针执行指针运算,而不是char*
  • @UnholySheep 好吧,这就是我想要的,我想“放置”WE 对象而不是字符。字符仅用于分配部分。
  • 是的,但是您分配了一个大小为 nbytes * sizeof(char) 的数组,而不是 nbytes * sizeof(WE) - 您正在使用 for 循环迭代超出它的范围
  • for 循环应该是i &lt; elements; i++

标签: c++ memory-management allocation memory-alignment placement-new


【解决方案1】:

对于对象构造(新放置),您可以按字节/字符进行迭代:

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

【讨论】:

    猜你喜欢
    • 2020-07-07
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-11
    • 2018-02-08
    相关资源
    最近更新 更多