我们应该在函数中用 constexpr 定义变量吗

Posted

技术标签:

【中文标题】我们应该在函数中用 constexpr 定义变量吗【英文标题】:Should we define variable with constexpr in a function 【发布时间】:2021-10-03 22:07:25 【问题描述】:

不知道在函数中用constexpr定义变量是否有意义。

void func()  static const int i = 1; 
void func2()  constexpr const int i = 1; 

函数中的static const会在第一次函数调用时被初始化,那么函数中的constexpr呢?我知道constexpr 指定该对象应该在编译期间可用。那么这是否意味着func2 中的变量i 将在编译时进行评估,而func 中的i 则不会?

【问题讨论】:

对于在构造和销毁时没有副作用的类型(不执行 IO 或类似操作),由于编译器可以执行的优化,生成的二进制文件的结果可能会变得相同。从语言的角度来看,它们表达了两种不同的东西。 Does static constexpr variable inside a function make sense? 会回答您的问题吗? "注意staticconstexpr是完全相互独立的。static定义了对象在执行期间的生命周期;constexpr指定了对象在编译期间应该是可用的。编译和执行是不相交和不连续的,在时间和空间上都是如此。所以一旦程序编译完成,constexpr 就不再相关了。" "static const in a function will be initialized on the first function call" — 请注意,这基本上仅适用于非平凡类型。对于琐碎的,它们的二进制表示在程序中是硬编码的。现场演示:godbolt.org/z/hxPTGoanK(在机器码级别g中没有i的初始化)。 其实我很在意评估的时间。我刚刚重新编辑了我的问题。 在大多数情况下,constexpr 是首选解决方案。它是一个编译时间常数。附加信息:不需要constexpr 之后的const。而且,阅读你的问题,如果你可以在函数体中定义一个constexpr,那就去做吧,因为它会缩小范围。 【参考方案1】:

有一个重要的区别。

static local variable 在第一次调用时被初始化,因此在后续调用中不再使用它的声明。特别是静态局部变量的构造函数只被调用一次。 static const 是一个静态变量,也是一个常量:因此,它的值一旦在第一次调用时被初始化,就不能再更改了。

constexpr expression 是一个表达式,可以在编译时计算。因此,例如,constexpr 变量可以用作非类型模板参数。

一般来说,你不能使用简单的static const 作为模板参数,因为即使它是一个常量,它的实际值也可能不会在编译时确定;例如:

void f(int x)

     static const i = x;
     std::array<int, i> a; // Compile error!

但是,初始化为constant expression 的整型变量仍然可以用作非类型模板参数。所以,在问题的代码中,func2 的变量i 可以用作非类型模板参数。

【讨论】:

"你不能使用简单的静态常量作为模板参数" — 抱歉,这是不正确的(如果你真的是指 " 作为模板参数")。现场演示:godbolt.org/z/vf1GYf7x4. @DanielLangr,值得注意的是这仅适用于整数类型,因为它们在 constexpr 存在之前有特殊规则。其他类型的行为与所述相同。 constexpr 是否会使func2 中的变量i 在编译时被评估?或者i 都在编译时进行评估? @DanielLangr 嗯,正确,我不知道。我修改了答案。【参考方案2】:

存在一些差异。初始化是其中之一。让我们重命名变量,以便我们可以更轻松地讨论它们:

void func()  static const int i = 1;  //internal linkage
void func2()  constexpr const int a = 1;  //external linkage
    初始化

在上面的代码中,只有 a 是编译时常量。它应在编译时初始化。这个想法是在编译上花费时间并在运行时节省时间。但是,i 可以在编译时或运行时初始化。

至于你应该使用哪个?使用满足您需求的任何一种。

【讨论】:

它们是函数中的局部变量,因此链接不适用于它们。 static 只定义文件范围的链接,这不是。 感谢您的指出。我已经编辑了我的答案,只限于初始化差异。

以上是关于我们应该在函数中用 constexpr 定义变量吗的主要内容,如果未能解决你的问题,请参考以下文章

函数内的静态 constexpr 变量是不是有意义?

c++ 默认构造函数 constexpr 还是正确未定义?

关于constexpr

使用 constexpr 成员函数初始化 constexpr 成员变量

将 constexpr 添加到语言后是不是将变量声明为 const 多余?

我们如何理解关于 constexpr 的“如果可能”