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

C++临时对象构造是否先于成员函数实参求值?多标准版本问询

关于C++宏中构造函数与参数求值顺序的问题

不同C++标准下的结果存在差异,具体情况如下:

C++17及以后版本

在C++17及更新的标准里,成员函数调用的左侧对象表达式(也就是AbortHelper(__FILE__, __LINE__))会被完整求值,且一定会先于成员函数的实参(msg)求值。

这意味着当你写ABORT(GenerateAbortMsg());时,AbortHelper的构造函数肯定会先执行,对象创建完成后才会去调用GenerateAbortMsg()。哪怕这个函数抛出异常,AbortHelper的析构函数也会被触发,进而执行终止程序的逻辑,完全符合你的需求。

C11/C14版本

这两个版本的标准没有明确规定成员函数调用时,对象表达式和实参的求值顺序。编译器可以自由选择先计算msg,再创建AbortHelper对象;也可以反过来执行。

如果编译器选择先求值GenerateAbortMsg(),那要是这个函数抛出异常,AbortHelper的构造函数根本没机会执行,自然不会触发析构函数的终止逻辑,你的需求就无法得到保证。

C++03及更早版本

这些旧标准的规则和C11/C14一致,同样没有定义成员函数调用中对象表达式和实参的求值顺序,编译器可自行决定求值顺序,所以同样无法保证构造函数先于msg执行。

兼容旧标准的解决办法

如果要在C++17之前的版本实现你的需求,可以把宏改成这样:

#define ABORT(msg) do { \
    AbortHelper helper(__FILE__, __LINE__); \
    helper.Report(msg); \
} while(0)

这种写法里,helper对象会在msg求值前就被创建,不管哪个C++版本,都能确保构造函数先执行,哪怕msg抛出异常,析构函数也能触发终止逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:32:41