我怎么知道编译器是否C++编译时计算表达式



我有这样的代码

const int Value = 123 * 2 + GetOffset();

GetOffset 是一个返回intconstexpr函数。

如何确保在编译时确实计算了此表达式?

你为什么不把constexpr也用于价值?我认为它会要求编译器对其进行评估,

constexpr int Value = 123 * 2 + GetOffset();   

如果函数 GetOffset(( 很简单并且满足 constexpr 的要求。

要求是

  1. 该函数必须具有非 void 返回类型。

  2. 函数体不能声明变量或定义新类型。

  3. 正文只能包含声明、NULL 语句和单个返回陈述。

由于Getoffset()返回int,它满足了第一个。

您无法确保编译器执行此操作。通常需要启用优化,包括某种级别的函数内联。这些选项是什么取决于您的编译器及其版本。

可以检查生成的程序集,以查看它是否包含对GetOffset的调用或仅使用编译器确定的常量。

如果你也声明"Value"为constexpr怎么办?实际上,您永远无法确定是否在编译时评估了某些内容,但是在这种情况下,没有理由无法对其进行评估。

一种可能性是使用 std::ratio 。 从 C++11 标准的第 20.10.1 节:

此子子句描述比率库。它提供了一个类模板比率,该比率精确地表示任何有限有理数,分子和分母可由 intmax_t 类型的编译时常量表示。

因此,根据标准,这仅对编译时常量有效:

const int value = std::ratio<123 * 2 + GetOffset()>::num;

因此,这将保证在编译时计算表达式。 但是,它也不能保证在运行时不计算表达式。

你不能绝对确定;编译器只需要生成具有指定行为的代码,在编译或运行时计算它不会改变行为。

但是,编译器需要能够在编译时对此进行评估,因为它可以在只允许编译时常量(如数组大小和模板参数(的情况下使用;因此,理智的编译器没有理由不执行明显的优化。如果编译器没有(至少在启用优化的情况下(,请将其丢弃并找到更好的编译器。

您可以检查编译器生成的程序集,以查看它是否计算值;但这本身并不能保证将来的构建也会这样做。

考虑到我已经五年多没有使用C++了,建议成为标记方式的可能性很高,但是使用内联函数呢?

如果函数返回在编译时可用的某个预定义值,则编译器应该能够使用该值。

使用表达式创建单独的源文件。评估printf("#define MyExpression %d.n", expression); 。生成项目时,请为本机系统编译此源文件并执行它。将生成的输出作为标头包含在常规源中。

如果要确认初始值设定项是常量表达式,则可以使用constexpr说明符:

constexpr int Value = 123 * 2 + GetOffset();

如果它不是常量表达式,则编译失败。

理论上没有指定 constexpr 变量Value是否在翻译过程中实际计算 - 但在实践中您可以确定它是。

只是断言它:static_assert(Value == 123 * 2 + GetOffset(), "constexpr");没有比这更简单

的了。

最新更新