blo*_*d04 5 c++ lifetime placement-new language-lawyer c++20
std::array<std::byte, N> storage分配一些内存可以用作存储吗?例如,a.data()即使分配对象的生命周期与 无关,在 上调用placement-new 是否安全std::array?
std::aligned_storage_t在 C++23 中被弃用的原因是,它的 UB 植根于其设计(并且 API 很差,但在这个问题中并非如此),虽然它非常接近 的用例std::array,所以是否强制使用C 风格的数组std::byte storage[N]作为内存分配的存储,不是std::array(甚至可能std::vector)。
问题std::aligned_storage_t是,当您开始新对象的生命周期时,该std::aligned_storage_t对象的生命周期就结束了。[基本生活]p1:
\n\no类型的对象的生命周期
\nT在以下情况结束:\n
\n- [...]
\n- he 对象占用的存储空间 [...] 被未嵌套在o中的对象重用。
\n
因此,如果您要使用std::arrayas ,就好像它是一样std::aligned_storage_t,您将无法调用数组的任何成员函数,因为数组的生命周期将结束:
alignas(T) std::array<std::byte, sizeof(T)> arr;\nT* ptr = std::construct_at(reinterpret_cast<T*>(&arr), ...);\n// Lifetime of `arr` ends\n// arr.data(); // UB: lifetime of `std::array` has ended\nRun Code Online (Sandbox Code Playgroud)\n但是,由于您使用.data()的指针std::array,因此生命周期不会结束,因为该成员std::byte[N]将为新对象[intro.object]p3提供存储:
\n\n如果在与 N \xe2\x80\x9d 类型的 \xe2\x80\x9carray 或 N
\nunsigned char\xe2\x80\x9d 类型的 \xe2\x80\x9carray 的另一个对象 e 关联的存储中创建完整的对象,则该数组提供存储对于创建的对象如果 [...]std\xe2\x80\x8b::\xe2\x80\x8bbyte
并通过[intro.object]p4:
\n\n\n如果满足以下条件,则对象a嵌套在另一个对象b中:
\n\n
\n- a是b的子对象,或者
\n- b为a提供存储,或
\n- 存在一个对象c,其中a嵌套在c中,而c嵌套在b中。
\n
因此,用bstd::byte[N] =的成员arr和c = 新构造的对象实例化第二个选项,用c = 成员std::byte[N]和a = 新构造的对象和b =std::array<std::byte, N>对象实例化第三个选项。新构造的对象嵌套在std::array.
因此它可以像使用对象一样使用std::byte[N](std::array<std::byte, N>即为嵌套在 array/ 中的新对象提供存储std::array):
alignas(T) std::array<std::byte, sizeof(T)> arr;\nT* ptr = std::construct_at(reinterpret_cast<T*>(arr.data()), ...);\n// Lifetime of `arr` continues: The array provides storage for the `T` object.\nfor (std::byte repr : arr) {\n // bytes of the object representation of `*ptr`\n}\nT* ptr2 = std::launder(reinterpret_cast<T*>(arr.data()); // Points to the same object as `*ptr`\nRun Code Online (Sandbox Code Playgroud)\n