106

I have read numerous times that enforcing const-correctness in your C or C++ code is not only a good practice with regards to maintainability, but also it may allow your compiler to perform optimizations. However, I have read the complete opposite, too — that it does not affect performance at all.

Therefore, do you have examples where const correctness may aid your compiler with improving your program's performance?

john_science
  • 6,325
  • 6
  • 43
  • 60
shuhalo
  • 5,732
  • 12
  • 43
  • 60
  • 55
    Const-correctness is one of the BEST practices as regards to maintainability. If your C++ code is not const-correct, it is basically a pile of crap, waiting for disaster to strike. It is not intended to affect performance. –  Aug 08 '10 at 16:23
  • 2
    @Neil Butterworth: unfortunately the inverse is not true. – Beta Aug 08 '10 at 16:27
  • 7
    Here's an example where `const` made a performance difference: http://stackoverflow.com/questions/1121791/optimisation-of-division-in-gcc. It was essentially a quality-of-implementation issue, though. `const` didn't determine whether the compiler *could* legally make the optimisation, it just happened that version of the compiler failed to make it when it was missing. – Steve Jessop Aug 08 '10 at 16:34
  • 3
    I'm quite sure "morgennebel" missed a 'only' in the first sentence: It makes much more sense with "is not only a good practice". – IanH Aug 08 '10 at 17:03
  • 2
    @IanH Yes, I considered that. But the OP has had ample time to clarify. I get really ticked off by people that post questions and then simply disappear. –  Aug 08 '10 at 17:23
  • Martin, I think you're missing an 'only' after 'not' as in 'not only a good practice' – Catskul Jul 01 '11 at 21:38

4 Answers4

95

const correctness can't improve performance because const_cast and mutable are in the language, and allow code to conformingly break the rules. This gets even worse in C++11, where your const data may e.g. be a pointer to a std::atomic, meaning the compiler has to respect changes made by other threads.

That said, it is trivial for the compiler to look at the code it generates and determine if it actually writes to a given variable, and apply optimizations accordingly.

That all said, const correctness is a good thing with respect to maintainability. Otherwise, clients of your class could break that class's internal members. For instance, consider the standard std::string::c_str() -- if it couldn't return a const value, you'd be able to screw around with the internal buffer of the string!

Don't use const for performance reasons. Use it for maintainability reasons.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • 32
    "you'd be able to screw around with the internal buffer of the string!" - crucially, you'd be able to *accidentally* screw around with the internal buffer. Compiler errors due to `const` are signposts, saying, "you're doing something stupid". – Steve Jessop Aug 08 '10 at 16:32
  • 4
    ... and const-casts are signposts saying, "the author of this code is trying to do something clever" ;-) – Steve Jessop Aug 08 '10 at 16:35
  • 6
    @Steve Jessop - or const-cast are signposts saying "I'm trying to bolt up a const-correct bunch of code to a non-const-correct one, and I can't fix either one". Which, let me tell you, is in no way clever, just annoying. – Michael Kohne Aug 08 '10 at 16:49
  • 7
    @Michael - yes, fair point. Perhaps the original signpost isn't "you're doing something stupid", rather "someone's doing something stupid". – Steve Jessop Aug 08 '10 at 16:54
  • Godbolt and Arduino told me that const correctness is not just for fun. – dgrat Sep 14 '17 at 14:23
  • @dgrat: Do you have an example? – Billy ONeal Sep 20 '17 at 19:00
  • @BillyONeal Well one part was already answered below and it is clear which version should be slightly faster. For Arduino, the compiler tends to move variables with a const more likely into the flash memory instead of the RAM. Which is desirable as for smaller micro controllers RAM is limited. – dgrat Sep 21 '17 at 08:04
  • @dgrat: Marking *data* as being "born const" is different than observing const-correctness in a codebase. – Billy ONeal Sep 21 '17 at 19:19
  • Comparing the above answer and this answer: https://stackoverflow.com/a/357607/3736444 - I'm also confused. I understood that with `const_cast` you can't simply "remove" `const` and work with an object as it wasn't `const`. So `const` seems to me a good indicator for optimizations... Could anybody clarify? – Jarek C Jul 13 '20 at 07:03
44

Yes it can.

Most consts are purely for the benefit of the programmer and do not help the compiler optimize because it's legal to cast them away and so they don't tell the compiler anything useful for optimization. However, some consts cannot be (legally) cast away and these do provide the compiler with useful information for optimization.

As an example, access to a global variable defined with a const type can be inlined while one without a const type cannot be inlined because it might change at runtime.

https://godbolt.org/g/UEX4NB

C++:

int foo1 = 1;
const int foo2 = 2;

int get_foo1() {
    return foo1;
}

int get_foo2() {
    return foo2;
}

asm:

foo1:
        .long   1
foo2:
        .long   2
get_foo1():
        push    rbp
        mov     rbp, rsp
        mov     eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address
        pop     rbp
        ret
get_foo2():
        push    rbp
        mov     rbp, rsp
        mov     eax, 2 ; foo2 has been replaced with an immediate 2
        pop     rbp
        ret

In practical terms, keep in mind that while const can improve performance, in most cases it won't or it will but the change will not be noticeable. The primary usefulness of const is not optimization.


Steve Jessop gives another example in his comment on the original question which brings up something worth mentioning. In a block scope, it's possible for a compiler to deduce if a variable will be mutated and optimize accordingly, regardless of const, because the compiler can see all uses of the variable. In contrast, in the example above, it's impossible to predict if foo1 will be mutated since it could be modified in other translation units. I suppose a hypothetical sentient ultra-compiler could analyze an entire program and determine if it's valid to inline access to foo1... but real compilers can't.

Praxeolitic
  • 22,455
  • 16
  • 75
  • 126
  • @ericcurtin That's why I didn't mention the compiler in the answer. Normally, when posting generated assembly, I'd make sure to state the compiler and version, but this is an optimization that every major optimizing compiler will perform so I didn't want to give the impression that this was particular to one compiler. – Praxeolitic Mar 13 '18 at 01:12
  • 1
    @Acorn Here's the same example but with a class object: https://godbolt.org/z/R-Zfgc. Also, the variables in the example have external linkage. – Praxeolitic Mar 14 '19 at 09:04
8

A bit old, but still applies: http://www.gotw.ca/gotw/081.htm And some more: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
7

in my experience, no

For scalar variables, compiler is able to determine whenever the value is changed and perform necessary optimization itself.

For array pointers, const correctness is no guarantee that values are really constant in presence of potential aliasing problems. Hence compiler can not use const modifier alone to perform optimizations

if you are looking optimization, you should consider __restrict__ or special function modifiers/attributes: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Anycorn
  • 50,217
  • 42
  • 167
  • 261