std::start_lifetime_as是否禁止访问原缓冲区?C++23代码合规问题
C++23 std::start_lifetime_as 相关问题解答
代码片段
struct MyData { std::int32_t value; }; std::vector<char> read_from_net(); void send_over_net(std::vector<char>&); ... std::vector<char> buffer = read_from_net(); std::start_lifetime_as<MyData>(buffer.data())->value = 222; // (1) send_over_net(buffer); // (2)
假设buffer.data()处启动MyData生命周期的所有要求(如缓冲区大小足够、对齐正确等)均已满足,以下是问题解答:
1. 此代码是否存在未定义行为(UB)?如此启动生命周期并修改字段是否定义良好?
不存在UB,操作完全定义良好。std::start_lifetime_as<MyData>会在buffer.data()指向的存储区域合法启动MyData对象的生命周期,之后直接访问并修改其value成员符合C++23标准规定。
2. 在(2)处能否无UB地以字符形式访问原缓冲区?
可以无UB访问。根据C++标准,任何对象的对象表示都允许通过char、unsigned char或std::byte类型读取:
- 缓冲区未被
MyData占用的部分,原char对象生命周期仍在持续,直接访问合法; - 被
MyData占用的部分,原char对象生命周期虽已终止,但通过char访问该区域本质是读取MyData的字节表示,这是标准明确允许的操作。
3. std::start_lifetime_as仅启动新生命周期同时保留原对象的生命周期?
不是。缓冲区中被MyData覆盖的存储位置上,原char对象的生命周期会终止——当在一个对象的存储位置创建新对象时,若原对象类型非const限定(此处char满足),原对象生命周期自动结束。未被覆盖的缓冲区部分,原char对象的生命周期不受影响。
4. 在(2)之后,是否应使用std::launder(buffer.data())[0]以字符数组形式访问原缓冲区?
不需要使用std::launder:
- 未被
MyData覆盖的char对象,buffer.data()直接指向合法存活的char数组,无需清洗指针; - 被覆盖的区域,通过
char访问对象表示的操作本身不需要std::launder,标准允许直接通过字节类型访问任何对象的底层字节。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

