函数内的静态 constexpr 变量有意义吗?
如果我在一个函数中有一个变量(比如一个大数组),将它同时声明为 static
和 constexpr
是否有意义?constexpr
保证数组是在编译时创建的,那么 static
会无用吗?
If I have a variable inside a function (say, a large array), does it make sense to declare it both static
and constexpr
? constexpr
guarantees that the array is created at compile time, so would the static
be useless?
void f() {
static constexpr int x [] = {
// a few thousand elements
};
// do something with the array
}
static
在生成的代码或语义方面真的在做什么吗?
Is the static
actually doing anything there in terms of generated code or semantics?
推荐答案
简短的回答是 static
不仅有用,而且总是很受欢迎.
The short answer is that not only is static
useful, it is pretty well always going to be desired.
首先要注意static
和constexpr
是完全独立的.static
定义对象在执行期间的生命周期;constexpr
指定对象在编译期间应该可用.编译和执行在时间和空间上都是不相交和不连续的.所以一旦程序被编译,constexpr
就不再相关了.
First, note that static
and constexpr
are completely independent of each other. static
defines the object's lifetime during execution; constexpr
specifies that the object should be available during compilation. Compilation and execution are disjoint and discontiguous, both in time and space. So once the program is compiled, constexpr
is no longer relevant.
每个声明为 constexpr
的变量都是隐式的 const
但 const
和 static
几乎是正交的(除了交互使用 static const
整数.)
Every variable declared constexpr
is implicitly const
but const
and static
are almost orthogonal (except for the interaction with static const
integers.)
C++
对象模型 (§1.9) 要求除位域以外的所有对象至少占用一个字节的内存并具有地址;此外,在给定时刻在程序中可观察到的所有此类对象必须具有不同的地址(第 6 段).这并不完全要求编译器在每次调用具有本地非静态 const 数组的函数时都在堆栈上创建一个新数组,因为编译器可以避难于所提供的 as-if
原则可以证明没有其他这样的物体是可以观测到的.
The C++
object model (§1.9) requires that all objects other than bit-fields occupy at least one byte of memory and have addresses; furthermore all such objects observable in a program at a given moment must have distinct addresses (paragraph 6). This does not quite require the compiler to create a new array on the stack for every invocation of a function with a local non-static const array, because the compiler could take refuge in the as-if
principle provided it can prove that no other such object can be observed.
这并不容易证明,不幸的是,除非函数是微不足道的(例如,它不调用任何其他函数,其主体在翻译单元中不可见),因为数组,或多或少根据定义,是地址.因此,在大多数情况下,每次调用时都必须在堆栈上重新创建非静态 const(expr)
数组,这违背了能够在编译时计算它的意义.
That's not going to be easy to prove, unfortunately, unless the function is trivial (for example, it does not call any other function whose body is not visible within the translation unit) because arrays, more or less by definition, are addresses. So in most cases, the non-static const(expr)
array will have to be recreated on the stack at every invocation, which defeats the point of being able to compute it at compile time.
另一方面,一个本地static const
对象被所有观察者共享,而且即使它定义的函数从未被调用,也可能被初始化.所以以上都不适用,编译器不仅可以自由地生成它的单个实例;可以在只读存储中免费生成它的单个实例.
On the other hand, a local static const
object is shared by all observers, and furthermore may be initialized even if the function it is defined in is never called. So none of the above applies, and a compiler is free not only to generate only a single instance of it; it is free to generate a single instance of it in read-only storage.
所以你绝对应该在你的例子中使用 static constexpr
.
So you should definitely use static constexpr
in your example.
然而,在一种情况下,您不想使用 static constexpr
.除非 constexpr
声明的对象是 ODR-used 或声明的 static
,编译器可以自由地不包含它.这非常有用,因为它允许使用编译时临时 constexpr
数组,而不会用不必要的字节污染已编译的程序.在这种情况下,您显然不想使用 static
,因为 static
可能会强制对象在运行时存在.
However, there is one case where you wouldn't want to use static constexpr
. Unless a constexpr
declared object is either ODR-used or declared static
, the compiler is free to not include it at all. That's pretty useful, because it allows the use of compile-time temporary constexpr
arrays without polluting the compiled program with unnecessary bytes. In that case, you would clearly not want to use static
, since static
is likely to force the object to exist at runtime.
相关文章