C++20中std::move结合unique_ptr的代码是否存在未定义行为?
问题解答
代码分析与结论
这段代码在C17及后续标准(包括C20)中是定义良好的,不存在求值顺序导致的未定义行为。
详细解释
在C++17之前,函数实参的求值顺序是未指定的,这意味着a_ptr->Foo(std::move(a_ptr))中,std::move(a_ptr)有可能先于a_ptr->的求值步骤执行,导致后续调用Foo时使用的是已经被移动的空智能指针,进而访问无效内存,行为未定义。
但C++17调整了表达式求值顺序规则:对于成员访问表达式a->b,规定必须先完成a的求值,再处理b相关的部分。对应到这段代码,执行流程确实会像你描述的那样:
A* a_ptr_raw = a_ptr.operator->(); a_ptr_raw->Foo(std::move(a_ptr));
先通过a_ptr获取到指向A对象的原始指针,之后才会对函数实参std::move(a_ptr)求值——此时即使a_ptr被移动成空,已经拿到的原始指针依然有效,指向的A对象并未被销毁,所以Foo函数返回a_的操作是安全的,行为完全可预测。
内容的提问来源于stack exchange,提问作者cbhattac
相关产品推荐
相关产品推荐

