为何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
相关产品推荐
相关产品推荐

