Для определения констант времени компиляции интегральных типов, таких как следующие (в области функций и классов), какой синтаксис лучше всего?
static const int kMagic = 64; // (1)
constexpr int kMagic = 64; // (2)
(1)
работает также для компиляторов С++ 98/03, вместо этого (2)
требуется не менее С++ 11. Есть ли другие различия между ними? Должен ли тот или иной быть предпочтительным в современном коде на С++ и почему?
ИЗМЕНИТЬ
Я попробовал этот пример кода с Godbolt CE:
int main()
{
#define USE_STATIC_CONST
#ifdef USE_STATIC_CONST
static const int kOk = 0;
static const int kError = 1;
#else
constexpr int kOk = 0;
constexpr int kError = 1;
#endif
return kOk;
}
а для случая static const
это сгенерированная сборка по GCC 6.2:
main::kOk:
.zero 4
main::kError:
.long 1
main:
push rbp
mov rbp, rsp
mov eax, 0
pop rbp
ret
С другой стороны, для constexpr
это:
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 0
mov DWORD PTR [rbp-8], 1
mov eax, 0
pop rbp
ret
Хотя в -O3
в обоих случаях я получаю ту же (оптимизированную) сборку:
main:
xor eax, eax
ret
РЕДАКТИРОВАТЬ № 2
Я пробовал этот простой код (live on Ideone):
#include <iostream>
using namespace std;
int main() {
const int k1 = 10;
constexpr int k2 = 2*k1;
cout << k2 << '\n';
return 0;
}
который показывает, что const int k1
оценивается во время компиляции, как он использовал для вычисления constexpr int k2
.
Однако для double
s существует другое поведение. Я создал отдельный вопрос для этого здесь.