11

Do const declarations help the compiler (GCC) produce faster code or are they only useful for readability and correctness?

Zed Shaw has argued that const is useless or is overused in C/C++:

Next is all the bizarre fascination with const. For some odd reason C++ loves to make you slap const on every part of a declaration, and yet I get the same end result as C: a function is called. (...)

(From: http://librelist.com/browser//mongrel2/2010/7/15/c-verses-c++/#770d94bcfc6ddf1d8510199996b607dd )

MWB
  • 11,740
  • 6
  • 46
  • 91
  • 1
    Const, like many other C++ keywords is overloaded. When used for access control in passing a pointer/reference the optimizer cannot infer whether or not the underlying data may change due to aliasing. When used to initialize external/static constant data however the compiler does know that the variable may never change. One crucial case is embedded systems where large constant arrays may be placed directly into ROM rather than wasting precious RAM. – doynax Dec 19 '13 at 22:49
  • 10
    Honestly, his rant seems very much based on the fact he doesn't really know what he's doing in C++ (and doesn't care to). – Joseph Mansfield Dec 19 '13 at 22:50
  • 5
    Zed's comment about const is rather dumb. C++ doesn't make you do anything. The language doesn't make you type const anywhere. You can write an entire program without it. Other programmers might make dumb design decisions or use const and const_cast incorrectly, but there is nothing wrong with the language itself. – shawn1874 Dec 20 '13 at 00:09

4 Answers4

14

Yes. Here’s one concrete example. const makes it possible to pass arguments by const& rather than by value (which might require a costly copy). It’s important to realise that the alternative to pass-by-const& is not pass-by-& because the latter doesn’t allow temporaries to be bound. So, for instance, this code:

auto result = foo{1} + foo{2} + foo{3};

may call foo operator +(foo const&, foo const&) but it may not call foo operator +(foo&, foo&).

That way, const helps avoid copies.

But generally, const is a tool to ensure correctness, not to to aid optimisations.

Either way, Zed Shaw has no idea what he’s talking about. The rest of his rant is similarly misinformed, by the way.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
7

No, const does not help the compiler make faster code. Const is for const-correctness, not optimizations.

The C++ standard says that const items can't be modified, but also says that const_cast should remove the const modifier from an object and make it writable (unless it's located in actually read-only memory, in which case the behavior is undefined); as such const cannot mean, in general, that the target variable will not change.

I can only think of these two very narrow scenarios where having const produces faster code than not having it:

  • the variable is global with internal linkage (static) and is passed by reference or pointer to a function defined in a different translation unit (different file). In this case, the compiler cannot elide reads to it if it is not marked const;
  • the variable is global with external linkage (extern). Reads to a const extern can be elided inside the file that defines it (but nowhere else).

When const is applied to a global variable, the compiler is allowed to assume that the value will never change because it will place it in read-only memory, and this means undefined behavior if the program attempts to modify it, and compiler authors love to rely on the threat of undefined behavior to make code faster.

Note that both scenarios apply only to global variables, which probably make for a very minor portion of the variables in your program. To its merit, however, const implies static at the global level in C++ (this is not the case in C).

Someone above said that using const can make code faster because it's possible to use const references. I would argue here that what make the code faster is the use of a reference, not the use of const.

That said, I still believe const is a very sharp knife with which you can't cut yourself and I would advise that you use it whenever it's appropriate, but don't do it for performance reasons.

zneak
  • 134,922
  • 42
  • 253
  • 328
  • 1
    `const_cast` cannot always be applied. `const` declarations *can* guarantee that an object doesn’t change, and thus simplify program flow analysis and elide memory reads. – Konrad Rudolph Dec 19 '13 at 23:02
  • @KonradRudolph, no matter if the variable is marked `const` or not, the compiler will be able to elide memory reads if it sees that the variable is never written to. In this case, `const` helps because it implies static linkage by default, and as such `const` variables have their scope limited just like if they had the `static` modifier. A non-const static variable that never changes will benefit from the same optimizations. – zneak Dec 19 '13 at 23:08
  • But sometimes the compiler *doesn’t* see this – when the (`const`-declared) variable is passed to a function (via `const&`) outside its translation unit. Here, the only way for the compiler to prove that the variable isn’t modified is to rely on its `const`-ness. – Konrad Rudolph Dec 19 '13 at 23:09
  • In which case it can't do read elision, because it needs to pass the value. – zneak Dec 19 '13 at 23:10
  • It can elide *subsequent* reads (= after the function call). – Konrad Rudolph Dec 19 '13 at 23:10
  • 1
    Remember 1 single use-case out of billions of lines of code is sufficient to make a statement true. "const" *can* make code faster and/or smaller; wether it will do so in your case does not matter. Also with most situations, understanding the code by the human reader, perhaps decades later, overrides performance, provided the code is sufficiently performant to meet the performance specification. – David V. Corbin Jun 23 '22 at 10:21
4

Yes, const can (not guaranteed) help the compiler produce faster/more correct code. More so than not, they're just a modifier on data that you express to both the compiler and to other people that read your code that some data is not supposed to change. This helps the type system help you write more correct software.

More important than optimizations, they just prevent your own code and people using your code from writing to data you assume to be invariant.

yan
  • 20,644
  • 3
  • 38
  • 48
  • Disagree with the first word of this response, which is the only part that OP appears confused about. Can you describe any example the answer "yes" is actually true? (Edit: never mind, see Konrad Rudolph's response, although honestly this is probably not what OP (or anyone else) had in mind.) – Andrey Mishchenko Dec 19 '13 at 22:55
  • 1
    @Andrey: Global/static initialized constant data is ROMable. This is taken advantage of by most embedded (von Neumann) compilers to save RAM. The same is true to a less extent on regular modern desktop systems where the such data may be shared between multiple running instances of software. – doynax Dec 19 '13 at 23:04
3

In general const modifier on method, references and pointers can't be used to optimize code for a couple of reasons. The primary one is that const modifier, in those contexts, doesn't make any guarantees about the underlying data not changing, it just makes it harder to modify it. Here is a classic example

void M(const C& p1, C& p2) { 
  cout << p1.field << endl;
  p2.Mutate();
  cout << p1.field<< endl;
}

In this case it's very possible that p1.field is modified in this code. The most obvious case is that p1 and p2 refer to the same value.

C local;
M(local, local);

Hence there is no real optimization the compiler can do here. The const parameter is equally as dangerous as the non-const one.

The other reason why it can't really optimize is that anyone can cheat in C++ with const_cast.

class C { 
public:
  int field;

  int GetField() const { 
    C* pEvil = const_cast<C*>(this);
    pEvil->field++;
    return field;
  }
};

So even if you are dealing with a single const reference the values are still free to change under the hood.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • I disagree with your arguments. While it is true that the compiler will have a hard time in trying to enforce your correct usage of `const` on member functions, `const` still serves as a hint to the compiler that you promise that the function does not alter the object's state. @KonradRudolph's answer is correct: When you declare a function `const` the compiler can assume that it actually is `const` and may thus avoid copying an object which is meant to be immutable. – JimmyB Aug 17 '18 at 11:02
  • The inverse of "In general" is quite different from "Never, It is Impossible" – David V. Corbin Jun 23 '22 at 10:23