11

In the answers to this question, (static constexpr vs constexpr in function body?), it is stated that static constexpr puts the variable in the .rodata section, whereas constexpr alone may allow initialising the variable at run-time.

IMPORTANT: This questions is about static variables within a function, not to do with linking external libraries.

My question is: in what situation would we prefer one of these two to the other in the code, in practice? Can one be better than the other for some codes? It is very hard to imagine how this can happen. After all, with either options, we can write codes in exactly the same way, with the same computational result. And the compiler can presumably optimise to make the better choice. So what does the programmer need to judge when choosing?

10
  • Please read more about storage duration and linkage. Commented Jul 15, 2023 at 20:34
  • @Someprogrammerdude It is not about linkage. It is within a function. Commented Jul 15, 2023 at 20:40
  • Please make your questions self contained. If it's based on another question, then yes link to that, but also please include examples and code and information inside the question itself. Commented Jul 15, 2023 at 20:53
  • static of a variable in a function is about storage duration. constexpr is the object can be used at compile-time. Commented Jul 15, 2023 at 21:30
  • 2
    C++ doesn't have .rodata sections. Your compiler might, but then you're asking about a particular tool chain, not about what static and constexpr mean in the C++ programming language. Commented Jul 15, 2023 at 22:15

1 Answer 1

22

If you don't use a constexpr variable as an lvalue (i.e., you only read its value but don't use its address) then its storage duration doesn't matter. The static constexpr variable and automatic constexpr variable are not odr-used (only their value is used), and will be optimized out. For instance, with GCC:

int f(bool b) { int unused = 999; // At -O1, this is optimized out constexpr int x = 123; // At -O1, this is optimized out static constexpr int y = 456; // At -O0, this is optimized out if (b) { return x; // Replaced with "return 123;" at -O0 (x not actually used) } else { return y; // Replaced with "return 456;" at -O0 } } 

However, there is a difference when used as an lvalue. It can make your code wrong:

const char* name(bool b) { static constexpr char name[2][6] = { "false", "true\0" }; return name[b]; // Would be dangling if name was not `static` } 

Or it can have performance impacts:

unsigned permute(unsigned i) { [[assume(i < 10)]]; constexpr int table[10] = { 4, 5, 8, 2, 3, 1, 9, 6, 0, 7 }; return table[i]; } 

Since table was not declared static, it will copy the initializer onto the stack and then index the stack. The initializer will be stored in the .rodata section. If table was static, return table[i]; would just index into something in the .rodata section.

It looks like clang is smart enough to optimize this specific case (GCC isn't), but there will be differences if you want to pass a large constant block to a void unknown_external_function(const void*); (the compiler will be forced to copy onto the stack if the constexpr variable isn't static).

It's hard to think of a situation where you would want to use an automatic constexpr variable over a static constexpr variable, other than pre-C++23 where constexpr functions can't declare static constexpr variables.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.