Коротка відповідь полягає в тому, що не тільки 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після закінчення компіляції вона перестає бути значимою, тому не можна нічого відкидати (і, можливо, взагалі нічого, тому що об’єкт навіть не гарантовано існує під час виконання.)