如果我有一个函数(比方说,一个大阵列)内的变量,它是有意义的声明它既static
和constexpr
? constexpr
保证数组在编译时创建的,因此将在static
没用?
void f() {
static constexpr int x [] = {
// a few thousand elements
};
// do something with the array
}
是static
实际上做任何那里产生码或语义方面?
简短的回答是,不仅是static
有用的,它是很好总是不理想。
首先,请注意static
和constexpr
是完全相互独立的。 static
执行期间定义了对象的生存期; constexpr
指定对象应该是在编译过程中可用。 编译和执行不相交和不连续的,无论是在时间和空间。 因此,一旦该程序被编译, constexpr
不再相关。
每个变量声明constexpr
是隐含const
,但是const
和static
几乎正交(除了与互动static const
整数)。
在C++
对象模型(§1.9)需要比位字段占据的存储器的至少一个字节,并具有地址,所有其他对象; 此外在给定时刻在一程序可观察到的所有这样的目的必须有不同的地址(第6段)。 这并不完全需要编译器创建堆栈与当地的非静态常量数组的函数的每次调用上一个新的数组,因为编译器可以投靠as-if
原则,只要能证明没有其他类似可以观察对象。
这不是一件容易的事证明,不幸的是,除非功能是微不足道的(例如,它不调用任何其它函数体是不是翻译单元内可见),因为数组定义或多或少,都是地址。 因此,在大多数情况下,非静态const(expr)
阵列将有堆栈在每次调用,这违背了能够计算出它在编译时间点上重新创建。
在另一方面,本地static const
对象由所有观察员共享,即使它是在定义的函数没有被调用还可以初始化。 所以,以上都不是应用,而编译器是免费的,不仅产生只有它的一个实例; 它是免费的,以生成它在只读存储器中的单个实例。
所以,你一定要使用static constexpr
在你的榜样。
然而,有一个情况下,你不希望使用static constexpr
。 除非constexpr
声明的对象要么ODR使用的或声明的static
,编译器是免费不包括它在所有。 这是非常有用的,因为它允许使用编译时刻暂时的constexpr
阵列不污染不必要的字节编译的程序。 在这种情况下,你会显然不是想用static
,因为static
有可能迫使该对象在运行时存在。