Коротка відповідь полягає в тому, що не тільки static
корисно, але й цілком добре завжди буде бажано.
По-перше, зауважте, що static
і constexpr
абсолютно незалежні один від одного. static
визначає термін експлуатації об'єкта під час виконання; constexpr
вказує, що об'єкт повинен бути доступний під час компіляції. Компіляція та виконання є непересічними та суперечливими як у часі, так і в просторі. Тож як тільки програма складена, constexpr
вона вже не актуальна.
Кожна змінна оголошена constexpr
неявно , const
але const
і static
майже ортогональні (для взаємодії з виключенням static const
цілих чисел.)
C++
Об'єктна модель (§1.9) вимагає , щоб всі об'єкти, крім бітових полів займають щонайменше , один байти пам'яті і мають адреси; крім того, всі такі об'єкти, що спостерігаються в програмі в даний момент, повинні мати чіткі адреси (параграф 6). Це не зовсім вимагає від компілятора створити новий масив у стеку для кожного виклику функції з локальним нестатичним масивом const, оскільки компілятор може притулитися за as-if
принципом за умови, що він може довести, що жоден інший такий об'єкт не може бути спостерігається.
На жаль, це не буде легко довести, якщо тільки функція не є тривіальною (наприклад, вона не викликає жодної іншої функції, тіло якої не видно в блоці перекладу), оскільки масиви, більш-менш за визначенням, є адресами. Тож у більшості випадків нестатичний const(expr)
масив повинен бути відтворений у стеку при кожному виклику, що втрачає точку можливості його обчислити під час компіляції.
З іншого боку, локальний static const
об'єкт ділиться всіма спостерігачами, і, крім того, він може бути ініціалізований, навіть якщо функція, визначена в ньому, ніколи не викликається. Отже, жодне з перерахованого вище не застосовується, і компілятор вільний не лише генерувати лише один його примірник; вільно генерувати один екземпляр його у сховищі лише для читання.
Тож вам обов’язково слід використовувати static constexpr
у своєму прикладі.
Однак є один випадок, коли ви не хочете користуватися static constexpr
. Якщо constexpr
задекларований об'єкт не використовується або ODR, або декларується static
, компілятор не може взагалі його включати. Це досить корисно, оскільки дозволяє використовувати тимчасові constexpr
масиви часу компіляції без забруднення складеної програми зайвими байтами. У такому випадку ви явно не хочете використовувати static
, оскільки static
це, ймовірно, змусить об'єкт існувати під час виконання.
const
відconst
об'єкта, тільки зconst X*
яких вказує наX
. Але це не суть; справа в тому, що автоматичні об'єкти не можуть мати статичні адреси. Як я вже говорив,constexpr
після закінчення компіляції вона перестає бути значимою, тому не можна нічого відкидати (і, можливо, взагалі нічого, тому що об’єкт навіть не гарантовано існує під час виконання.)