5

While watching a C++11 tutorial video linked on isocpp.org I noticed something:

constexpr int windowWidth{800}, windowHeight{600};

What is the point in declaring these int variables as constexpr, and not just const?

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • 1
    possible duplicate of [const vs constexpr on variables](http://stackoverflow.com/questions/13346879/const-vs-constexpr-on-variables) – perreal Dec 01 '13 at 06:27

2 Answers2

6

Nice video Vittorio!

Here is a summary of the difference between declaring an int const and constexpr:

int get_int();  // Some run time function that returns int

template <int N>  // example use requiring a compile time int
struct test {};

const     int w = get_int();  // initialized at run time
const     int x = 5;          // initialized at compile time
constexpr int y = get_int();  // error, can not initialize at compile time
constexpr int z = 6;          // initialized at compile time

int
main()
{
    test<w> tw;  // error, w is not a compile time constant
    test<x> tx;  // ok, x is a compile time constant
    test<y> ty;  // error, there is no compile time constant named y
    test<z> tz;  // ok, z is a compile time constant
}

When you use constexpr, you require that the initialization happens at compile time, lest you will get a compile time error. When you use const, you allow the initialization to happen at run time, though it will still happen at compile time if the initializer is itself a compile time constant.

If you have a const int, the code reviewer must look at the initialization (following back to the original if this is a copy of a const int) to know if that const int is a compile time constant, or a run time constant.

If you have a constexpr int, the code reviewer can immediately assume that it is a compile time constant without analyzing how it was initialized. If that assumption turns out to be false, the compiler will flag it as an error.

<Disclaimer>

In the comments below Kerrek SB correctly points out that I've played "fast and loose" with the terminology in this answer. I've done so in an effort to make the answer short and understandable. What I'm calling "initialized at compile time" and "compile time constant" are what the standard in section 5.19 "Constant expressions" [expr.const] refers to as integral constant expressions.

Integral constant expressions are initialized with what is called constant initialization, which together with zero-initialization is referred to as static initialization ([basic.start.init]/p2).

Any deviations between what I write here and what appears in the standard are accidental, and what is in the standard is correct.

</Disclaimer>

Community
  • 1
  • 1
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • "Initialized at compile time" doesn't really make sense. Initialization is part of the program *execution*. "Initialized statically" would be better, though I wouldn't protest "at load time". Also, C++ actually mandates when something must be initialized statically (like `const int x = 5;`), there is no arbitrariness. The only arbitrariness is that dynamic initialization *may* be hoisted into the static phase. – Kerrek SB Dec 01 '13 at 21:00
  • @KerrekSB: Fair enough. – Howard Hinnant Dec 01 '13 at 22:37
  • so const int y =1984; and constexpr int y = 1984; will generate identical asm code? Or not identical but identical in a sense it wont do assignment during runtime? – NoSenseEtAl Dec 02 '13 at 09:56
  • @NoSenseEtAl: Identical. But consider `const int y = z` vs `constexpr int y = z`. You can't answer the question without first figuring out if `z` is an integral constant expression. And if `z` is not an integral constant expression, the latter will not even compile. – Howard Hinnant Dec 02 '13 at 15:42
5

I'm the author of the video.

Intent.

constexpr clearly expresses the intent of a compile-time immutable value. const doesn't really mean compile-time immutable value.

Both modifiers can be casted away, but that results in undefined behavior. Check DyP's comment for more information.

When using C++11, in my opinion, the first keyword that should come to mind when dealing with compile-time values is not const but constexpr.

The code would behave exactly the same without constexpr, or with const in place of constexpr. But when you take a look at the code, and see constexpr int windowWidth; you can be 100% sure that's an immutable constant that will never change during run-time.


In my second tutorial video, there's an addendum on constexpr in the first three minutes, that shows constexpr functions and more constexpr examples/explanations.

Community
  • 1
  • 1
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • 3
    *"`const` is a modifier that can even be casted away, so it doesn't really mean compile-time immutable value"* I think `constexpr` isn't really even part of the type of an object, it just implies `const` and adds restrictions on the type and the initialization. You can cast away constness from both, const-declared and constexpr-declared variables; modifying through such a non-const path leads to UB. The important point is *compile-time*: a const-declared variable can be initialized with a value that's known only at run-time, unlike constexpr-declared variables. – dyp Dec 01 '13 at 12:23