Имеет ли смысл статическая переменная 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вероятно, чтобы заставить объект существовать во время выполнения.