Compile-time constants and variables
Compile time constant must be:
- declared final
- primitive or String
- initialized within declaration
- initialized with constant expression
So private final int x = getX();
is not constant.
To the second question private int y = 10;
is not constant (non-final in this case), so optimizer cannot be sure that the value would not change in the future. So it cannot optimize it as good as constant value. The answer is: No, it is not treated the same way as compile time constant.
confused about compile time constants
"Compile Time" or "Compiling" is one part of the process. In C++, there is a feature called Macros that are expanded into C++ code during the Pre-Processor stage. This Pre-Processor stage runs first before the compiler. Depending on the compiler, the next step is to convert the human-readable C++ code to another form that is readable by machines. This really depends on the type of the compiler and other possible arguments passed in during compilation as to what this turns into. For sake of simplicity, let's assume the compiler compiles the C++ to symbols/assembly/machine code. Each of these files is independent, for lack of better term.
The last step is to 'link these together. Includes, forward declarations, and externs are resolved during this stage. The once independent files now 'linked' with sizes of types/classes/structs known at the end of the stage. After all this is done, an executable is formed for which is purely machine language and understood by the computer running the program.
A general rule of thumb for C++ programming is you want to catch as many errors as possible at compile time. Run-time is the span of time for which your program is executing the machine code. This can include heap allocations, dynamic list resizing, etc...
Now, to the crux of your question. What is the difference between a Run-Time constant and Compile Time constant? It is quite simple. Compile Time constants are values known and resolvable at compile time. These values can be determined and calculated and depend on no external user input or file data. See constexpr as a good reference for learning more about compile time constants: ConstExprLink.
const int userScore = 3; // Compile time constant
const int secondUserScore = 5; // Compile time constant
constexpr int CombinedUserScores = ( userScore + secondUserScore ); // Also compile constant because all values are known at compile time
However, there are some constants that cannot be known at compile time. These values can be determined and resolved after your program Run-Time begins. Now, in contrast, imagine you are reading user input or data from a file during Run-Time
std::cout << "Enter your Test Score: ";
const int testScore = 0;
std::cin >> testScore; // User sets an input value during Run-Time
const int userScore { testScore }; // Run-Time constant. No way to know the value at compile time
userScore is now a Run-Time constant that cannot be changed unless you engage in some taboo stuff like const_cast or C style casts. The point here is that the compiler has no way to know what the value of this constant would be until the input is read in. This is often called Data-Driven programming and is a very common paradigm. Also, because the Run-Time const is not determined at compile time, constexpr cannot be used here.
The above is an example of a Run-Time constant. This value cannot be resolved at compile time because the compiler has no idea what the input from the user or file might be. Here is another good reference: CompileTimeConstant Versus RunTimeConstant
Where to define compile-time constants?
In C++17, defining compile-time integer constants is easy.
First, you should decide whether or not the constant should be scoped to a class. If it makes sense to have it as a class member (e.g., it pertains to the concept that the class represents) then make it a class member. Otherwise, don't.
As a class member, write:
class JolloManager {
constexpr static int rounds = 3;
};
That's it. No out-of-line definition is required anymore in C++17.
If it's not going to be a class member, but you want everyone who includes your header to be able to access the value, then write this in the header:
inline constexpr int rounds = 3;
(Technically, the reason to use inline
is to avoid ODR violations when the variable is ODR-used by an inline function in multiple translation units.)
If the value is an implementation detail that only one .cpp
file needs access to, then write the following in that .cpp
file to give it internal linkage (i.e., prevent clashing with names in other translation units):
constexpr int rounds = 3; // no `inline` this time
Finally, if the constant is only needed by a single function, you can make it local to that function:
void foo() {
constexpr int rounds = 3;
}
how to guarantee initilization of a stack variable with a compile time constant
I think it is better to use consteval
function, but if you cannot change it, you can simply use a temporary variable which will surely optimize later:
constexpr int func( int i )
{
return i+2;
}
int main()
{
constexpr int i1 = func(8);
auto i2 = i1;
i2 = 9;
}
Although you may not like this method, I think it works without any problem....
You can also use something like this(Based on StoryTeller idea):
template<typename T> constexpr std::remove_const_t<T> const_eval(T&& res) { return res; }
which support returning references from method too.
Difference between final variables and compile time constant
The problem is, that all case:
statements must be ultimate at compile time.
Your first statement is ultimate. a
will for 100% be no other value than 5
.
final int a = 5;
However, this is not guaranteed for b
. What if there would be an if-statement around b
?
final int b;
if(something())
b=6;
else
b=5;
Related Topics
How to Obtain Mouse Click Coordinates Outside My Window in Java
Convert Java.Time.Localdate into Java.Util.Date Type
The Meaning of Noinitialcontextexception Error
Eclipse: Attach Source/Javadoc to a Library via a Local Property
What's the Difference Between Spring Data's Mongotemplate and Mongorepository
Converting Integers to Roman Numerals - Java
How to Use Aop with Aspectj for Logging
Why Can't I Use a Type Argument in a Type Parameter with Multiple Bounds
Providing Input/Subcommands to Command Executed Over Ssh with Jsch
Differencebetween I++ & ++I in a for Loop
Why Is T Bounded by Object in the Collections.Max() Signature
Adding Image to Jbutton with Foreground Label
In Java, When Should I Create a Checked Exception, and When Should It Be a Runtime Exception