哪些操作会触发指定存储位置对象的生命周期终止?
C++对象生命周期终止问题解析
场景示例
#include <array> #include <cstddef> #include <cstdint> #include <memory> struct S { alignas(std::uint64_t) alignas(std::uint32_t) std::array<std::byte, sizeof(std::uint64_t)> storage = { /* some init values */ }; }; int main() { S s; // 显式在存储位置创建uint64_t对象 auto pi64 = std::start_lifetime_as<std::uint64_t>(s.storage.data()); // 显式在同一存储位置创建uint32_t对象 auto pi32 = std::start_lifetime_as<std::uint32_t>(s.storage.data()); }
核心问题解答
1. 第二次调用std::start_lifetime_as是否会终止之前的uint64_t对象生命周期?
是的。根据C++标准,当在已被某个对象占用的存储区域上创建新对象时,只要新对象的存储与原有对象的存储存在重叠,原有对象的生命周期立即终止——无论新对象的大小是否完全覆盖原有对象的存储。
示例中,两次std::start_lifetime_as调用都以storage.data()作为起始地址,新创建的uint32_t对象与之前的uint64_t对象存储区域重叠,因此原有uint64_t的生命周期被终止。
2. 还有哪些操作会触发此类生命周期终止?
以下是几种常见的触发原有对象生命周期终止的操作:
- Placement new表达式:直接在原有对象的存储位置构造新对象,比如你提到的
new (storage.data()) std::byte[sizeof(std::uint64_t)],只要存储区域重叠,原有对象的生命周期就会终止。 std::construct_at函数:该函数是placement new的封装,用于在指定地址构造新对象,同样会终止重叠存储上的原有对象生命周期。- 联合(Union)成员切换:当激活联合的另一个成员时,当前活跃成员的生命周期会终止(对于非平凡类型,需先显式调用析构函数;平凡类型无需额外操作)。
- 隐式生命周期类型的存储覆盖:对于
std::byte、char、unsigned char这类隐式生命周期类型,直接覆盖其存储内容并将该存储用作其他对象的存储时,原有对象(如果存在)的生命周期会自动终止。 std::start_lifetime_as_array函数:与std::start_lifetime_as类似,用于在指定地址创建数组对象,同样会终止重叠存储上的原有对象生命周期。
注意:对于非平凡类型,在终止其生命周期前建议显式调用析构函数,避免资源泄漏(placement new、
std::construct_at等操作不会自动析构原有对象)。
内容的提问来源于stack exchange,提问作者Oersted
相关产品推荐
相关产品推荐

