【问题标题】:Creating/destroying an object in a static memory section在静态内存部分创建/销毁对象
【发布时间】:2021-08-02 10:37:20
【问题描述】:

静态内存部分alignas(alignof(T)) char bytes[sizeof(T)] 是否适合通过调用std::construct_at(bytes, ...) / std::destroy_at(bytes) 在其生命周期内保存T 的实例?我的直觉说,是的,对齐和大小要求是有保证的,所以在构造之后(因为也有简单可构造的类型,我更喜欢称它为初始化)reinterpret_cast<T*>(bytes) 是一个指向完全有效类型T 实例的有效指针.

我错过了什么吗?

PS:我也可以写 std::aligned_storage_t<sizeof(T), alignof(T)> bytes - 在这种情况下,它的内存将被引用为 &bytesstd::addressof(bytes)

【问题讨论】:

    标签: c++ memory language-lawyer memory-alignment object-lifetime


    【解决方案1】:

    静态内存部分 alignas(alignof(T)) char bytes[sizeof(T)] 是否适合通过调用 std::construct_at(bytes, ...) / std::destroy_at(bytes) 在其生命周期内保存 T 的实例?

    是的。

    reinterpret_cast<T*>(bytes) 是指向 T 类型的完全有效实例的有效指针。

    我错过了什么吗?

    你仍然需要清洗一个指向重用内存的指针:

    T* ptr1 = std::construct_at(reinterpret_cast<T*>(bytes), ...); // valid
    T* ptr2 = std::launder(reinterpret_cast<T*>(bytes)); // valid
    std::destroy_at(ptr2); // valid, just like std::destroy_at(ptr1)
    

    【讨论】:

    • 好收获! std::launder 对我来说总是很模糊,即使它在 C++17 之前并不存在,我们只是做了一个 reinterpret_cast
    • @plasmacel 是的,在那之前我们只需要玩 UB,或者总是只使用placement new 返回的指针。
    • 我是否也应该清洗传递给std::destroy_at的指针?喜欢std::destroy_at(std::launder(reinterpret_cast&lt;T*&gt;(bytes)));
    • @plasmacel 是的,从bytes 获取指针时,您必须始终清洗。
    • 请注意,std::construct_at 采用指针类型T*,其中T 是您要为其创建实例的类型。所以实际上是std::construct_at(std::launder(reinterpret_cast&lt;T*&gt;(bytes)), ...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多