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

为何std::move可移动栈数据对象?相关代码运行存疑求解

问题分析与解答

代码示例

int *pOuter = nullptr;
{
    int j;
    std::cout << "top of the inner stack=" << &j << std::endl;
    int aData[] = {1,2,3,4,5};  // in a vanishing stack
    aData[0] = 0;  // to make sure that aData is on stack
    int *pInner = aData;
    std::cout << "Before Move: pOuter=" << pOuter << ", pInner=" << pInner << std::endl;
    pOuter = std::move(pInner);
    std::cout << "After Move: pOuter=" << pOuter << ", pInner=" << pInner << std::endl;
}
// aData[0] and pInner are no longer accessible
int i;
std::cout << "top of the outer stack=" << &i << std::endl;
int aCover[] = {10,9,8,7,6,5,4,3,2,1};  // to reclaim stack
std::cout << "aCover=" << aCover << ", pOuter=" << pOuter << ": ";
for (i = 0; i < 5; ++i) {
    std::cout << *(pOuter + i) << ",";
}
std::cout << std::endl;

运行输出

top of the inner stack=0xb2125ff7cc
Before Move: pOuter=0, pInner=0xb2125ff7b0
After Move: pOuter=0xb2125ff7b0, pInner=0xb2125ff7b0
top of the outer stack=0xb2125ff804
aCover=0xb2125ff7d0, pOuter=0xb2125ff7b0: 0,2,3,4,5,

结论:你的判断完全正确

  • std::move对原始指针仅做值拷贝,不会改变指针指向的内存状态。内部作用域结束后,aData所在的栈帧被释放,pOuter成为悬垂指针,访问该指针属于C++标准定义的未定义行为。
  • 从地址分布来看,编译器确实提前为外部栈变量(i、aCover)分配了空间,aCover的地址位于aData的高地址区域,没有覆盖aData原有的栈内存,这才让旧数据暂时保留。但这是编译器的实现细节,不同编译器、编译选项或运行环境下,结果可能完全不同。
  • 这次运行正常只是巧合,未定义行为的表现不可预测:可能输出正确值、乱码,甚至直接触发段错误、导致程序其他逻辑异常。本质上pOuter已经是无效指针,任何对它的解引用操作都是非法的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 01:51:24