const vs constexpr on variables

Is there a difference between the following definitions?

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

If not, which style is preferred in C++11?

2

5 Answers

I believe there is a difference. Let's rename them so that we can talk about them more easily:

const double PI1 = 3.141592653589793; constexpr double PI2 = 3.141592653589793; 

Both PI1 and PI2 are constant, meaning you can not modify them. However only PI2 is a compile-time constant. It shall be initialized at compile time. PI1 may be initialized at compile time or run time. Furthermore, only PI2 can be used in a context that requires a compile-time constant. For example:

constexpr double PI3 = PI1; // error 

but:

constexpr double PI3 = PI2; // ok 

and:

static_assert(PI1 == 3.141592653589793, ""); // error 

but:

static_assert(PI2 == 3.141592653589793, ""); // ok 

As to which you should use? Use whichever meets your needs. Do you want to ensure that you have a compile time constant that can be used in contexts where a compile-time constant is required? Do you want to be able to initialize it with a computation done at run time? Etc.

17

No difference here, but it matters when you have a type that has a constructor.

struct S { constexpr S(int); }; const S s0(0); constexpr S s1(1); 

s0 is a constant, but it does not promise to be initialized at compile-time. s1 is marked constexpr, so it is a constant and, because S's constructor is also marked constexpr, it will be initialized at compile-time.

Mostly this matters when initialization at runtime would be time-consuming and you want to push that work off onto the compiler, where it's also time-consuming, but doesn't slow down execution time of the compiled program

2

constexpr indicates a value that's constant and known during compilation.
const indicates a value that's only constant; it's not compulsory to know during compilation.

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 

Note that const doesn’t offer the same guarantee as constexpr, because const objects need not be initialized with values known during compilation.

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 

All constexpr objects are const, but not all const objects are constexpr.

If you want compilers to guarantee that a variable has a value that can be used in contexts requiring compile-time constants, the tool to reach for is constexpr, not const.

2

A constexpr symbolic constant must be given a value that is known at compile time. For example:

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

To handle cases where the value of a “variable” that is initialized with a value that is not known at compile time but never changes after initialization, C++ offers a second form of constant (a const). For Example:

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 } 

Such “const variables” are very common for two reasons:

  1. C++98 did not have constexpr, so people used const.
  2. List item “Variables” that are not constant expressions (their value is not known at compile time) but do not change values after initialization are in themselves widely useful.

Reference : "Programming: Principles and Practice Using C++" by Stroustrup

1

One more example to understand the difference between const and constexp.

int main() { int n; cin >> n; const int c = n; // OK: 'c' can also be initialized at run time constexpr int e = n; // Error: 'e' must be initialized at compile time } 

Note: constexpr normally evaluated at compile-time, but they are not guaranteed to do so unless they're invoked in a context where a constant expression is required.

constexpr int add(int a, int b) { return a + b; }; int main() { int n = add(4, 3); // may or may not be computed at compile time constexpr int m = add(4,3); // must be computed at compile time } 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like