Const vs constexpr для переменных
Есть ли разница между следующими определениями?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
Если нет, какой стиль предпочтительнее в С++ 11?
Ответы
Ответ 1
Я считаю, что есть разница. Позвольте переименовать их, чтобы мы могли легче говорить о них:
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
Оба PI1
и PI2
являются постоянными, то есть вы не можете их изменять. Однако только PI2
является константой времени компиляции. Он должен инициализироваться в собранном времени. PI1
может быть инициализирован во время компиляции или времени выполнения. Кроме того, только PI2
может использоваться в контексте, который требует постоянной времени компиляции. Например:
constexpr double PI3 = PI1; // error
а
constexpr double PI3 = PI2; // ok
и
static_assert(PI1 == 3.141592653589793, ""); // error
а
static_assert(PI2 == 3.141592653589793, ""); // ok
Что вы должны использовать? Используйте то, что соответствует вашим потребностям. Вы хотите, чтобы у вас была константа времени компиляции, которая может использоваться в контекстах, где требуется постоянная времени компиляции? Вы хотите, чтобы иметь возможность инициализировать его с помощью вычислений, выполненных во время выполнения? Etc.
Ответ 2
Здесь нет никакой разницы, но имеет значение, если у вас есть тип, у которого есть конструктор.
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0
является константой, но она не обещает быть инициализированной во время компиляции. s1
отмечен constexpr
, поэтому он является константой и, поскольку конструктор S
также помечен constexpr
, он будет инициализирован во время компиляции.
В большинстве случаев это имеет значение, когда инициализация во время выполнения будет трудоемкой, и вы хотите оттолкнуть эту работу на компилятор, где она также занимает много времени, но не замедляет время выполнения скомпилированной программы
Ответ 3
constexpr указывает значение, которое является константой и известно во время компиляции.
const указывает значение, которое только константа; это не обязательно знать во время компиляции.
int sz;
constexpr auto arraySize1 = sz; // error! sz value unknown at compilation
std::array<int, sz> data1; // error! same problem
constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr
Обратите внимание, что const не предоставляет ту же гарантию, что и constexpr, потому что const
объекты не обязательно должны быть инициализированы значениями, известными во время компиляции.
int sz;
const auto arraySize = sz; // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize value unknown at compilation
Все объекты constexpr являются константами, но не все объекты const являются constexpr.
Если вы хотите, чтобы компиляторы гарантировали, что переменная имеет значение, которое может быть
используется в контекстах, требующих константы времени компиляции, инструментом для достижения является constexpr, а не const.
Ответ 4
Символьная константа A constexpr должна иметь значение, известное во время компиляции.
Например:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
constexpr int c2 = n+7; // Error: we don’t know the value of c2
// ...
}
Чтобы обрабатывать случаи, когда значение "переменной", которое инициализируется значением, которое неизвестно во время компиляции, но никогда не изменяется после инициализации,
С++ предлагает вторую форму константы (a const).
Например:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
const int c2 = n+7; // OK, but don’t try to change the value of c2
// ...
c2 = 7; // error: c2 is a const
}
Такие переменные const очень часто встречаются по двум причинам:
- У С++ 98 не было constexpr, поэтому люди использовали const.
- Элемент списка "Переменные", которые не являются постоянными выражениями (их значение неизвестно во время компиляции), но не меняют значения после
инициализация сама по себе является весьма полезной.