40

I often use const for local variables that are not being modified, like this:

const float height = person.getHeight();

I think it can make the compiled code potentially faster, allowing the compiler to do some more optimization. Or am I wrong, and compilers can figure out by themselves that the local variable is never modified?

Frank
  • 64,140
  • 93
  • 237
  • 324
  • I wouldn't be surprised. – chris May 25 '12 at 02:58
  • 1
    AFAIK const doesn't do anything with optimization, volatile does – zar May 25 '12 at 03:00
  • Optimisations are more practical when values are compile-time const. A more general discussion that may interest you can be found here: http://stackoverflow.com/questions/212237/constants-and-compiler-optimization-in-c – Tony Delroy May 25 '12 at 03:06
  • @zadane, I'm pretty sure it does open up certain optimizations. However, don't forget that premature optimization is the root of all evil. Pondering over this for this purpose is a waste of time. Once your program's running, choose a better algorithm or something if you need to speed it up. – chris May 25 '12 at 03:07
  • 5
    @chris: _"premature optimization is the root of all evil"_ all you have to do is add a const. Please explain to me how this can be evil. If anything, it will make the code more safe, which is the exact opposite of evil. Also, the whole quote goes _"Premature optimization is the root of all evil. **Yet we should not pass up our opportunities in that critical 3%."**_. Source: [link](http://c2.com/cgi/wiki?PrematureOptimization) – Tara Apr 26 '16 at 08:07
  • Adding or subtracting consts isn't going to affect code structure, unless someone has gone in for highly undesireable polymorphisms based on const qualifiers. But it can often help the compiler out, for example const objects cannot alias, which is a big problem C++ compilers face. – Malcolm McLean Oct 05 '16 at 11:02
  • @Tara It isn't in this case. Not all premature optimizations are "evil". It's just adding a const to a variable, nothing else. There are many cases where PO aren't. I program with optimizations in my mind, as long as the overall design isn't compromised. – chila Oct 18 '21 at 11:04
  • @Chila I cannot tell whether you are agreeing with me or disagreeing. I have the feeling you have not properly read my comment. – Tara Oct 18 '21 at 18:06
  • @Tara Sorry I miss-tagged. – chila Nov 16 '21 at 13:55
  • @chris It isn't in this case. Not all premature optimizations are "evil". It's just adding a const to a variable, nothing else. There are many cases where PO aren't. I program with optimizations in my mind, as long as the overall design isn't compromised. – chila Nov 16 '21 at 13:56

5 Answers5

51

Or am I wrong, and compilers can figure out by themselves that the local variable is never modified?

Most of the compilers are smart enough to figure this out themselves.
You should rather use const for ensuring const-correctness and not for micro-optimization.
const correctness lets compiler help you guard against making honest mistakes, so you should use const wherever possible but for maintainability reasons & preventing yourself from doing stupid mistakes.

It is good to understand the performance implications of code we write but excessive micro-optimization should be avoided. With regards to performance one should follow the,

80-20 Rule:

Identify the 20% of your code which uses 80% of your resources, through profiling on representative data sets and only then attempt to optimize those bottlenecks.

Robert
  • 767
  • 8
  • 17
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • +1 u wrote what i thought i would write when i saw the question. i think i would have mentioned the words "constraints" and "clarity", though. however. :-) – Cheers and hth. - Alf May 25 '12 at 03:29
  • One more thing to add: after compilers verify const-correctness, they might remove const qualifiers from the variables before compiling to the machine code. – mercury0114 Jan 27 '23 at 08:41
18

This performance difference will almost certainly be negligible, however you should be using const whenever possible for code documentation reasons. Often times, compilers can figure this out for your anyway and make the optimizations automatically. const is really more about code readability and clarity than performance.

Oleksi
  • 12,947
  • 4
  • 56
  • 80
2

If there is a value type on the left hand, you may safely assume that it will have a negligible effect, or none at all. It's not going to influence overload resolution, and what is actually const can easily be deduced from the scope.


It's an entirely different matter with reference types:

std::vector<int> v(1);
const auto& a = v[0];
auto& b = v[0];

These two assignments resolve to two entirely different operators, and similar overload pairs are found in many libraries aside STL too. Even in this simple example, optimizations which depend on v having been immutable for the scope of b are already no longer trivial and less likely to be found.

The STL is still quite tame in these terms though, in such that at least the behavior doesn't change based on choosing the const_reference overload or not. For most of STL, the const_reference overload is only tied to the object being const itself.

Some other libraries (e.g. Qt) make heavy use of copy-on-write semantics. In these const-correctness with references is no longer optional, but necessary:

QVector<int> v1(1);
auto v2 = v1; // Backing storage of v2 and v1 is still linked
const auto& a = v1[0]; // Still linked
const auto& b = v2[0]; // Still linked
auto& c = v2[0]; // Deep copy from v1 to v2 is happening now :(
// Even worse, &b != &c

Copy-on-write semantics are something commonly found in large-matrix or image manipulation libraries, and something to watch out for.

It's also something where the compiler is no longer able to save you, the overload resolution is mandated by C++ standard and there is no leeway for eliminating the costly side effects.

Ext3h
  • 5,713
  • 17
  • 43
1

I don't think it is a good practice to make local variables, including function parameters, constant by default.

The main reason is brevity. Good coding practices allow you to make your code short, this one doesn't.

Quite similarly, you can write void foo(void) in your function declarations, and you can justify it by increased clarity, being explicit about not intending to pass a parameter to the function, etc, but it is essentially a waste of space, and eventually almost fell out of use. I think the same thing will happen to the trend of using const everywhere.

Marking local variables with a const qualifier is not very useful for most of the collaborators working with the code you create. Unlike class members, global variables, or the data pointed to a by a pointer, a local variable doesn't have any external effects, and no one would ever be restricted by the qualifier of the local variable or learn anything useful from it (unless he is going to change the particular function where the local variable is).

If he needs to change your function, the task should not normally require him to try to deduce valuable information from the constant qualifier of a variable there. The function should not be so large or difficult to understand; if it is, probably you have more serious problems with your design, consider refactoring. One exception is functions that implement some hardcore math calculations, but for those you would need to put some details or a link to the paper in your comments.

You might ask why not still put the const qualifier if it doesn't cost you much effort. Unfortunately, it does. If I had to put all const qualifiers, I would most likely have to go through my function after I am done and put the qualifiers in place - a waste of time. The reason for that is that you don't have to plan the use of local variables carefully, unlike with the members or the data pointed to by pointers.

They are mostly a convenience tool, technically, most of them can be avoided by either factoring them into expressions or reusing variables. So, since they are a convenience tool, the very existence of a particular local variable is merely a matter of taste.

Particularly, I can write:

  • int d = foo(b) + c;
  • const int a = foo(b); int d = a + c;
  • int a = foo(b); a += c

Each of the variants is identical in every respect, except that the variable a is either constant or not, or doesn't exist at all. It is hard to commit to some of the choices early.

  • 6
    Omitting `const` makes it slightly quicker to write code, but significantly slower to read/understand/maintain that code. In particular, if I see `const int a = foo(b)` at the top of a function, then as I read through the remainder of the function I can rest assured that `a` will have that same value at all points in the function. Without the `const` keyword, I no longer have that guarantee, and if I want to know what the value of `a` is at a particular location I will have to manually traverse all the code-paths between `a`'s declaration and that point-of-use to try and figure it out. – Jeremy Friesner Jul 05 '18 at 21:35
  • @JeremyFriesner: Another benefit of `const` is that using it with a struct whose address is passed to outside could would invite a compiler to assume that the outside code won't change its contents--an assumption to which the compiler would not otherwise be entitled. – supercat Jul 16 '18 at 20:04
  • @supercat You'd think so, but in practice the compiler isn't typically able to use the presence of `const` as an opportunity to make additional optimizations, because it's usually impractical for the compiler to prove that no other function could possibly still modify the const-pointed-to-object behind the scenes, via some other route. See: https://stackoverflow.com/questions/27466642/what-kind-of-optimization-does-const-offer-in-c-c-if-any – Jeremy Friesner Jul 16 '18 at 20:19
  • 1
    @JeremyFriesner: A compiler can't apply such optimizations to const-qualified *pointers*, but if the declaration that allocates space for an object qualifies it as `const` but not `const volatile`, there would be no means by which the object, within its lifetime, could ever hold any value other than what was used in its initializer (without invoking UB). – supercat Jul 16 '18 at 20:24
-3

There is one major problem with local constant values - as shown in the code below:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// const uint32_t const_dummy = 0;

void func1(const uint32_t *ptr);

int main(void) {
    const uint32_t const_dummy = 0;
    func1(&const_dummy);
    printf("0x%x\n", const_dummy);
    return EXIT_SUCCESS;
}

void func1(const uint32_t *ptr) {
    uint32_t *tmp = (uint32_t *)ptr;
    *tmp = 1;
}

This code was compiled on Ubuntu 18.04.

As you can see, const_dummy's value can be modified in this case! But, if you modify the code and set const_dummy scope to global - by commenting out the local definition and remove the comment from the global definition - you will get an exception and your our program will crash - which is good, because you can debug it and find the problem.

What is the reason? Well global const values are located in the ro (read only) section of the program. The OS - protects this area using the MMU. It is not possible to do it with constants defined in the stack.

With systems that don't use the MMU - you will not even "feel" that there is a problem.

Yedhu Krishnan
  • 1,225
  • 15
  • 31
yoav Segal
  • 11
  • 2
  • This is wrong. It's Undefined Behavior whether the const variable is local or global. It just happens to have different effects in reality. But a realistic outcome would, for example, be for the program as you wrote it to still be `0`. – Sebastian Redl Aug 05 '20 at 12:28
  • The code a I just provide is terrible - but it came to introduce anothe view of the issue. By using objdump - one can see where the const variable is located if it is defined as global. I suggest grabbing the code , and check it both with global and local definitions. Just comment out the right definitions. – yoav Segal Aug 06 '20 at 07:14
  • It still doesn't matter. Modifying a variable initially declared const through a cast is undefined behavior. It's irrelevant what the concrete output of the compiler is. Do not write programs doing this. – Sebastian Redl Aug 06 '20 at 08:02
  • Nobody writes a program like this. And yet, there are different ways to override the contents of the "const" local variable using memcpy to a nearby address of a local variable or something like that. And I've worked with programmers who managed to ruin the contents of local const variables - without really understanding what happened. – yoav Segal Aug 06 '20 at 08:35
  • Tehre is no valid C++ program where the contetnts of a const changes. – Sebastian Redl Aug 06 '20 at 08:37
  • What is the meaning of valid? One can find programmers who do bad things in their code. This very bad program can be built and executed on Linux using Eclipse CDT. – yoav Segal Aug 06 '20 at 08:49
  • 1
    "What is the meaning of valid?" - The C++ standard defines what a valid program is. – Sebastian Redl Aug 06 '20 at 11:16