Короткий ответ заключается в том, что это не только 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
, вероятно, вынудите объект существовать во время выполнения.
const
отconst
объекта, только изconst X*
которых указывает наX
. Но дело не в этом; Дело в том, что автоматические объекты не могут иметь статические адреса. Как я уже говорил,constexpr
перестает быть значимым , как только компиляция закончится, так что нет ничего разбрасывать (и , вполне возможно , вообще ничего, так как объект не гарантируется даже существовать во время выполнения.)