Имеет ли смысл статическая переменная constexpr?
если у меня есть переменная внутри функции (скажем, большой массив), имеет ли смысл объявлять ее как static
и constexpr
? constexpr
гарантии, что массив создается во время компиляции, так static
бесполезно?
void f() {
static constexpr int x [] = {
// a few thousand elements
};
// do something with the array
}
- это static
на самом деле делать что-нибудь там с точки зрения сгенерированного кода или семантики?
1 ответ:
короткий ответ заключается в том, что не только
static
полезно, это довольно хорошо всегда будет желанным.во-первых, обратите внимание, что
static
иconstexpr
полностью независимы друг от друга.static
определяет время жизни объекта во время выполнения;constexpr
указывает, что объект должен быть доступен во время компиляции. Компиляция и выполнение являются непересекающимися и несвязными, как во времени, так и в пространстве. Поэтому, как только программа будет скомпилирована,constexpr
больше не соответствующий.каждая переменная, объявленная
constexpr
неявноconst
ноconst
иstatic
почти ортогональны (за исключением взаимодействия сstatic const
целых чисел.)The
C++
объектная модель (§1.9) требует, чтобы все объекты, отличные от битовых полей, занимали по крайней мере один байт памяти и имели адреса; кроме того, все такие объекты, наблюдаемые в программе в данный момент, должны иметь различные адреса (пункт 6). Это не совсем требует компилятора чтобы создать новый массив в стеке для каждого вызова функции с локальным нестатическим массивом const, потому что компилятор может укрыться вas-if
принцип при условии, что он может доказать, что никакой другой такой объект не может наблюдаться.это будет нелегко доказать, к сожалению, если функция не является тривиальной (например, она не вызывает никакой другой функции, тело которой не видно в единице перевода), потому что массивы, более или менее по определению, являются адреса. Так что в большинстве случаев, нестатические
const(expr)
массив должен быть воссоздан в стеке при каждом вызове, что не позволяет вычислить его во время компиляции.С другой стороны, местный
static const
объект является общим для всех наблюдателей, и, кроме того, может быть инициализирован, даже если функция, в которой он определен, никогда не вызывается. Таким образом, ничто из вышеперечисленного не применяется, и компилятор свободен не только генерировать только один экземпляр; он свободен генерировать один экземпляр его в хранилище только для чтения.так что вы обязательно должны использовать
static constexpr
в вашем примере.однако, есть один случай, когда вы не хотели бы использовать
static constexpr
. Еслиconstexpr
объявленный объект либо ODR-используется или объявленыstatic
, компилятор может не включать его вообще. Это довольно полезно, потому что это позволяет использовать время компиляции temporaryconstexpr
массивы без загрязнения скомпилированной программы ненужными байты. В этом случае вы явно не захотите использоватьstatic
сstatic
вероятно, чтобы заставить объект существовать во время выполнения.