Имеет ли значение статическая переменная constexpr?

Если у меня есть переменная внутри функции (скажем, большой массив), имеет ли смысл объявить ее обе static а также constexpr? constexpr гарантирует, что массив создается во время компиляции, так что static быть бесполезным?

void f() {
static constexpr int x [] = {
// a few thousand elements
};
// do something with the array
}

Это static на самом деле делать что-то там с точки зрения сгенерированного кода или семантики?

133

Решение

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

160

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector