константный против таких переменных


есть ли разница между следующими определениями?

const     double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;

если нет, то какой стиль предпочтительнее в C++11?

4 204

4 ответа:

Я считаю, что есть разница. Давайте переименуем их, чтобы мы могли говорить о них более легко:

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

о том, что вы должны использовать? Используйте то, что соответствует вашим потребностям. Вы хотите убедиться, что у вас есть константа времени компиляции, которая может использоваться в контекстах, где требуется константа времени компиляции? Вы хотите иметь возможность инициализировать его с помощью вычисления, выполненного во время выполнения? Так далее.

здесь нет разницы, но это имеет значение, когда у вас есть тип, который имеет конструктор.

struct S {
    constexpr S(int);
};

const S s0(0);
constexpr S s1(1);

s0 является константой, но она не обещает быть инициализирована во время компиляции. s1 отмечается constexpr, так это константа и, потому что Sконструктор также отмечен constexpr, он будет инициализирован во время компиляции.

в основном это имеет значение, если инициализация во время выполнения потребуется много времени, и вы хотите, чтобы подтолкнуть эту работу на компилятор, где это также занимает много времени, но не замедляет время выполнения скомпилированной программы

constexpr указывает значение, которое является постоянным и известным во время компиляции.
const указывает значение, которое является только константой; это не обязательно знать во время компиляции.

int sz;
constexpr auto arraySize1 = sz;    // error! sz's 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's value unknown at compilation

все объекты пользователем константные, но не все объекты const constexpr.

Если вы хотите компиляторы, чтобы гарантировать, что переменная имеет значение, которое может быть используемый в контекстах, требующих констант времени компиляции, инструмент для достижения является constexpr, а не const.

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
    // ...
}

для обработки случаев, когда значение "переменной", которая инициализируется со значением, не известен во время компиляции, но не меняется после инициализации, C++ предлагает вторую форму константы (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 переменные" очень распространены две причины:

  1. C++98 не имел constexpr, поэтому люди использовали const.
  2. элемент списка "переменные", которые не являются постоянными выражениями (их значение не известно во время компиляции) , но не изменяют значения после инициализация сама по себе широко полезна.

ссылка : "Программирование: Принципы и практика использования C++" от Страуструпа