静态constexpr变量有意义吗?

问题描述 投票:154回答:1

如果我在函数内部有一个变量(比如一个大数组),那么将它声明为staticconstexpr是否有意义? constexpr保证数组是在编译时创建的,所以static会无用吗?

void f() {
    static constexpr int x [] = {
        // a few thousand elements
    };
    // do something with the array
}

在生成代码或语义方面,static实际上是在做什么吗?

c++ static c++11 constexpr
1个回答
185
投票

简短的回答是,static不仅有用,而且总是很需要。

首先,请注意staticconstexpr完全相互独立。 static定义了对象在执行期间的生命周期; constexpr指定在编译期间对象应该可用。编辑和执行在时间和空间上都是不相交和不连续的。因此,一旦编制了该程序,constexpr就不再适用了。

声明constexpr的每个变量都是隐含的const,但conststatic几乎是正交的(除了与static const整数的相互作用。)

C++对象模型(§1.9)要求除位字段之外的所有对象占用至少一个字节的内存并具有地址;此外,在特定时刻在程序中可观察到的所有这些对象必须具有不同的地址(第6段)。这并不需要编译器在每次使用本地非静态const数组调用函数时在堆栈上创建一个新数组,因为编译器可以避免使用as-if原则,前提是它可以证明没有其他此类对象可以被观察。

遗憾的是,这并不容易证明,除非函数是微不足道的(例如,它不会调用其体在翻译单元中不可见的任何其他函数),因为根据定义,数组或多或少是地址。因此,在大多数情况下,必须在每次调用时在堆栈上重新创建非静态const(expr)数组,这样就无法在编译时计算它。

另一方面,所有观察者共享本地static const对象,并且即使从未调用其定义的函数,也可以初始化该对象。因此,以上都不适用,并且编译器不仅可以自由生成它的单个实例;可以在只读存储中生成单个实例。

所以你绝对应该在你的例子中使用static constexpr

但是,有一种情况你不想使用static constexpr。除非constexpr声明的对象是ODR-used或声明static,否则编译器可以根本不包含它。这非常有用,因为它允许使用编译时临时constexpr数组,而不会用不必要的字节污染编译的程序。在这种情况下,您显然不想使用static,因为static可能会强制对象在运行时存在。

© www.soinside.com 2019 - 2024. All rights reserved.