1

In C++, does a mathematical declaration in a constant variable initialization costs some extra processing? Or modern compilers would automatically put the result of the mathematical calculation inside the variable when creating the .exe file?

So e.g.:

MyClass::MyClass()
{
    const qint32 defaultX = 20;

    poButton1 = new PushButton(this);
    poButton1->move(defaultX,20);

    poButton1 = new PushButton(this);
    poButton1->move(defaultX,80);
    //...
}

is a example of a code that uses a constant variable (defaultX) across a method usage (the constructor in this case). Now sometimes it's better for the developer to tell where the value came from:

MyClass::MyClass()
{
    const qint32 defaultX = 800/2 - 244 + 12 + 32 - 180; //just an example!

    poButton1 = new PushButton(this);
    poButton1->move(defaultX,20);

    poButton1 = new PushButton(this);
    poButton1->move(defaultX,80);
    //...
}

Of course he could just put that inside a comment, but let's suppose he wants to do it this way (e.g.: he is dumb). The question would then be: when a object of that class is being initialized, does that whole mathematical expression is calculated (costing extra processing) or when the .exe is created by modern compilers it already contains the optimized code seen in the first MyClass code?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
Momergil
  • 2,213
  • 5
  • 29
  • 59
  • 3
    As long as the expression is constant, a decent compiler will optimize it away and replace defaultX with the result of the expression. In C++11, you might want to use `constexpr` instead. – Filipe Gonçalves Aug 07 '14 at 17:57
  • 1
    In theory there's no guarantee in either direction. In fact, every halfway reasonable compiler you can find will do it at compile time. – Jerry Coffin Aug 07 '14 at 17:57
  • Why do you think it's dumb to do so? There might be reasons to clarify how values are constructed, or you want to use other constant expressions in the formula. And no, it doesn't harm runtime performance, the compiler will calculate everything correctly at compile time, same way as you start your pocket calculator to do so. – πάντα ῥεῖ Aug 07 '14 at 17:57
  • @πάνταῥεῖ I suggested a "dumbness" explanation since, once having the possibility to write the formula in a commentary while putting only the result in the code, having at the same time the possibility of 'harming' runtime performance, there would be no reasonable reason AFAIK for doing that :) – Momergil Aug 08 '14 at 17:57

2 Answers2

3

It is not guaranteed but most modern compilers will indeed fold the constant expression, the draft C++ standard has a note that says constant expressions could be evaluated during translation, from section 5.19 Constant expressions:

[ Note: Constant expressionscan be evaluated during translation.—end note ]

but we can run an experiment on godbolt with the following code:

#include <iostream>
int func()
{
    const  int defaultX = 800/2 - 244 + 12 + 32 - 180; //just an example!

  return defaultX ;
}

int main()
{
  std::cout << func() ;
}

and see it does indeed fold it to the following:

func():
  movl  $20, %eax   #,
  ret

In C++11 you can always use constexpr to make sure it is evaluated at compile time:

constexpr  int defaultX = 800/2 - 244 + 12 + 32 - 180;

The standard does make one important note with respect to floating point constant expressions. Since there is a lack of specification on the accuracy of floating point operations it is possible that evaluations at run-time and compile-time could produce different results:

[ Note: Although in some contexts constant expressions must be evaluated during program translation, others may be evaluated during program execution. Since this International Standard imposes no restrictions on the accuracy of floating-point operations, it is unspecified whether the evaluation of a floating-point expression during translation yields the same result as the evaluation of the same expression (or the same operations on the same values) during program execution.84 Example:

 bool f() {
  char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during translation
  int size = 1 + int(1 + 0.2 - 0.1 - 0.1); // May be evaluated at runtime
  return sizeof(array) == size;
 }

It is unspecified whether the value of f() will be true or false. —end example ] —end note ]

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
2

If it can be collapsed into a single value, which it must be in the case of a simple assignment, the compiler should take care of condensing it down to a singular value, though this may depend on your compiler's optimization flags. You may want to look at the instructions emitted by your compiler to be sure.

One way to express this more clearly is to declare the constant outside of the class itself but local to the implementation and use that within the class:

const qint32 myClassDefaultX = 800/2 - 244 + 12 + 32 - 180;

MyClass::MyClass() { ... }
tadman
  • 208,517
  • 23
  • 234
  • 262
  • IMHO this expression will always be calculated at compile time, regardless of any optimization settings. – πάντα ῥεῖ Aug 07 '14 at 17:59
  • @πάνταῥεῖ I'm not sure this is a *requirement* of a compliant compiler, but an obvious optimization many do. – tadman Aug 07 '14 at 18:06
  • 1
    May be you're right, the standard (§5.19) just mentions this behavior as a note: `[Note: Constant expressions can be evaluated during translation. — end note] `, so the compiler finally isn't required to implement it this way ;) ... – πάντα ῥεῖ Aug 07 '14 at 18:17