You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用reinterpret_cast的C++未定义行为及memmove隐式创建对象的疑问

关于std::memmove隐式创建对象与Data生命周期的问题

原代码的未定义行为

原代码中,char buf[sizeof(Data)]仅分配了足够容纳Data对象的内存,但**Data的生命周期并未启动**。后续通过reinterpret_cast将buff转为Data*并使用std::launder的操作属于未定义行为——因为此时内存中并没有存活的Data对象。

原代码如下:

#include <iostream>
#include <cstring>
struct Data{

};
void process(char * buff){
    decltype(auto) d = std::launder(reinterpret_cast<Data *>(buff));
}
int main() {
     char buf[sizeof(Data)];
     process(buf);
}

cppreference关于std::memmove的说明

std::memmove may be used to implicitly create objects in the destination buffer.
(翻译:std::memmove可用于在目标缓冲区中隐式创建对象)

修改后的代码

修改后的代码通过调用std::memmove(buff, buff, sizeof(Data))尝试触发对象的隐式创建,代码如下:

#include <iostream>
#include <cstring>
struct Data{

};
void process(char * const buff){
    decltype(auto) d = std::launder(reinterpret_cast<Data *>(std::memmove(buff,buff,sizeof(Data))));
}
int main() {
   char buf[sizeof(Data)];
   process(buf);
}

问题解答

1. memmove能否隐式启动Data的生命周期,消除未定义行为?

可以。按照C++标准的规定,std::memmove的这种自复制调用(把buff指向的内存复制到自身,且缓冲区大小刚好能容纳Data对象)会触发隐式对象创建。因为Data是平凡类型,满足隐式创建的所有条件:内存大小足够、对齐要求符合,而且原内存里只有char数组——char类型的对象生命周期可以被新创建的Data对象覆盖。这时候用reinterpret_cast配合std::launder获取Data*就是合法操作,原代码的未定义行为也就不存在了。

2. 这个Data对象的生命周期何时结束?

这个隐式创建的Data对象,生命周期会持续到它所在的内存区域被释放,或者被其他对象覆盖。在这个例子里,buf是main函数里的栈上数组,所以当main执行完、栈帧被销毁时,buf的内存被回收,Data对象的生命周期也就跟着结束了。如果后续有代码修改buf的内容(比如在main里process调用之后写buf),那也会提前结束这个Data对象的生命周期。

内容的提问来源于stack exchange,提问作者getsoubl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:42:41