为什么C++中同行调用多个函数与分行调用的运行结果存在差异?
问题原因
这个问题的核心是 C++旧版本标准对函数参数和子表达式的求值顺序没有明确规定,不同编译器可以自行决定求值顺序,进而触发未定义行为。
单行代码的异常逻辑分析
你写的单行代码如下:
getSomePtr(someUniquePtr.get(), someArray)->moveUniquePtr(std::move(someUniquePtr));
在C++17之前的标准中,整个表达式的所有子表达式求值顺序是未指定的,编译器完全可以按照以下顺序执行:
- 先执行
std::move(someUniquePtr),将someUniquePtr的所有权转移,此时someUniquePtr已经变为空 - 再执行
someUniquePtr.get(),这时候拿到的自然是空指针 - 调用
getSomePtr传入空指针,导致运行异常
拆分两行后正常的原因
拆分后的代码如下:
auto* somePtr = getSomePtr(someUniquePtr.get(), someArray); somePtr->moveUniquePtr(std::move(someUniquePtr));
C++规定不同语句之间的执行顺序是严格从上到下的,所以第一行getSomePtr调用、someUniquePtr.get()执行时,std::move操作还没有执行,someUniquePtr的所有权还在,拿到的指针是有效的,第一行执行完成后才会执行第二行的所有权转移逻辑,所以运行正常。
补充说明
C17及之后的标准已经对这类链式调用的求值顺序做了明确规定:函数调用的目标表达式求值会严格顺序在所有参数求值之前,所以如果你的编译标准指定为C17及以上,单行写法也不会出现上述问题。
内容的提问来源于stack exchange,提问作者Matoy
相关产品推荐
相关产品推荐

