5

Example:

#define Var1 35
static const int Var1( 35);

So while #define replaces everywhere that I've used Var1 with 35 at compile time (which I presume makes the compile time slightly longer, if you have a lot of them, as it parses the code), using a static const int makes the compiler consider it a variable.

Does this mean that when using static const int it'll increase the memory imprint of my program because it has to use memory for all those constants, or is this overhead pretty much optimised out by the compiler anyway?

The reason I ask is because I'm wondering if it'd be better, for situations like this, to have them as static const ints in debug mode (so you can easily see the values while debugging) but make them #defines in release mode so it would make the program smaller.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Edward
  • 235
  • 4
  • 18
  • The size difference would be negligible, and changing the entire definition in your release version means you've not tested it properly in debug mode (because the code isn't the same). Unless you're in a very tight memory situation, declare them as `static const` and forget the premature optimization related to memory concerns for such a small savings. (You can reuse the same const declaration in multiple places if you put it in a single location and `#include` it.) – Ken White Dec 25 '14 at 01:22
  • 4
    If you can't trust the compiler to get trivial stuff like this right, you shouldn't trust it to do anything right and should use a different compiler. If you feel like you have to micromanage stuff like this, something is very wrong somewhere. – David Schwartz Dec 25 '14 at 01:29
  • Likely, the compiler will do the job for you. `static` stuff is very easy to optimize. – newbie Dec 25 '14 at 01:32
  • The optimizer will likely take care of this as a form of constant propagation, you can see in this similar question [Do temp variables slow down my program?](http://stackoverflow.com/q/26949569/1708801) even if the variables are not const the compiler can eliminate them. Using godbolt like I do in my answer you can investigate simple examples quickly. – Shafik Yaghmour Dec 25 '14 at 03:28

4 Answers4

4

Using macros to “make the program smaller” is ungood for several reasons:

  • Use of macros may instead make the program larger, or have no effect.
  • Macros don't follow the scoping rules in C++. You risk inadvertent text replacement.
  • Depending on the quality of the tools you may lose debug information.
  • The advantageous effect, if it occurs, is marginal.
  • The common convention for avoiding macro name clashes, namely ALL UPPERCASE, is an eyesore.

In short this is an example of a premature optimization.

And as Donald Knuth observed, premature optimizations are Evil™.


In passing, note that the static in

static const int Var1( 35);

… is redundant if this at namespace scope. A namespace scope constant has internal linkage by default. Just write

const int Var1 = 35;

… for the same effect, but IMHO more clear.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
3

If it is static then the compiler can see that it's only used inside of that translation unit and not have to wonder how it's used externally, which is an advantage. If you don't do anything making it have to be an actual variable (such as creating a pointer to it) then the compiler will often optimize it out.

A friendlier approach could be using enums

enum { Var1 = 35 };

or in C++11, constexpr

constexpr int Var1 = 35;

These also have the advantage of not messing with a variable of the same name in another scope, if you later had

void f() {
    int Var1;
}

The #define would turn it into int 35;

But the difference in memory used will be very small, likely so insignificant it will never have any measurable impact on performance unless you're in an extremely limited environment.

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
  • Hm, I find the argument in first para, dubious. I think you should elaborate on the imagined advantage. Regarding enums, great for C++03-compatible code when the constant is a class member (avoiding the need to provide an out-of-class definition). The `constexpr` is wholly redundant for a simple `int` namespace scope constant. It's already as constant as it can be, a compile time constant. – Cheers and hth. - Alf Dec 25 '14 at 01:44
  • @Cheersandhth.-Alf you are correct about the redundant namespace scope. I didn't realize it would have static linkage by virtue of it being constexpr. As for the first part, the advantage would just be what OP wants, which is to not have the static variable occupy memory. If there were a ton of them then the advantage might actually be noticeable – Ryan Haining Dec 25 '14 at 01:51
2

"Does this mean that when using static const int it'll increase the memory imprint of my program because it has to use memory for all those constants, or is this overhead pretty much optimised out by the compiler anyway?"

That's totally dependent on your actual compiler's implementation, and how well optimization features are done with it.

For the case of simple numerical constants, that come within a logical context I'd pefer using enum declarations anyway.
And most of the time I find using a static const int Var1( 35); is the better choice vs a #define'd value, because I have full control over the scope where it should be seen.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

Every decent compiler makes constant propagation to see which expression will remain constant. const helps the compiler in this job.

The next thing most compiler do very well is to remove unused parts of the code. This is why const variables which are not visible to the outside neither directly (local variables, static variables) nor indirectly (i.e. the address of the variable was not used as reference of for assigning a value to a pointer) are removed by the optimizer.

Example:

static const int e = 29;
int main() 
{
    int x = e; 
    return x + 1; 
}

Will be compiled by MSVC 2013 in release mode to :

PUBLIC  _main
_TEXT   SEGMENT
_main   PROC                        
    mov eax, 30                 ; optimized the code to return 30
    ret 0
_main   ENDP
_TEXT   ENDS
END                             ;  no place is reserved nowhere for the static.  
Christophe
  • 68,716
  • 7
  • 72
  • 138