12

I know for a function this simple it will be inlined:

int foo(int a, int b){
    return a + b;
}

But my question is, can't the compiler just auto-detect that this is the same as:

int foo(const int a, const int b){
    return a + b;
}

And since that could be detected, why would I need to type const anywhere? I know that the inline keyword has become obsolete because of compiler advances. Isn't it time that const do the same?

sepp2k
  • 363,768
  • 54
  • 674
  • 675
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • The point of `const` is to prevent future you to mistakenly modify a value. When reading a long function, if you see `const int x` at the start, you know that at line 300 `x` is still the same even without checking the previous code. – chi Apr 21 '15 at 11:40
  • 17
    You don't type `const` for the compiler so much as you type it for yourself. You are telling the compiler to kick you if you ever try to change its value. – Galik Apr 21 '15 at 11:41
  • 4
    Your example isn't a very good one. In this particular case, when the compiler lowers this into SSA form, it _will_ see that `a` and `b` are not assigned to and non-`volatile`, thus that they are effectively `const`, and act accordingly. `const` is far more powerful when it is applied to _pointers_, or is part of a function's interface (its signature), since then a compiler can rely on the promises of the function to optimize. – Iwillnotexist Idonotexist Apr 21 '15 at 11:42
  • 3
    I'm sure it can, and it does. If you optimize high compilers may re-order instructions etc. if they can prove that there are no alises or other side effects. – Peter - Reinstate Monica Apr 21 '15 at 11:43
  • 11
    `inline` is *far* from obsolete. It allows for multiple definitions of the function to exist in the program without violating ODR. – Angew is no longer proud of SO Apr 21 '15 at 11:43
  • there's also more reasons why you wouldn't like it to automatically "detect" something to be a "const", somewhat related; http://stackoverflow.com/questions/455518/how-many-and-which-are-the-uses-of-const-in-c – Thomas Lindvall Apr 21 '15 at 11:46
  • @Angew https://isocpp.org/wiki/faq/inline-functions says: "No matter how you designate a function as `inline`, it is a request that the compiler is allowed to ignore: the compiler might inline-expand some, all, or none of the places where you call a function designated as `inline`." Do you disagree with that? – Jonathan Mee Apr 21 '15 at 11:48
  • 1
    @JonathanMee No. Read the quote carefully - it's referring to inlining functions. You were talking about the `inline` keyword, which does *more* than just this ignorable request for inlining. – Angew is no longer proud of SO Apr 21 '15 at 11:50
  • @PeterSchneider I think that's my question then, why do we still qualify variables then? – Jonathan Mee Apr 21 '15 at 11:50
  • @Angew Can you give me an example? I am only aware of `inline` being used in reference to functions/methods. – Jonathan Mee Apr 21 '15 at 11:52
  • @ThomasLindvall Can you elaborate? I didn't see anything in the answers on why a compiler wouldn't be able to auto-detect a variable as `const`. – Jonathan Mee Apr 21 '15 at 11:55
  • 3
    @JonathanMee That's it. It marks the function as inline. The primary purpose of being inline is to allow a function to be defined in multiple translation units without violating ODR. It is *also* a non-binding request to the compiler to actually inline the function. But its semantics is ODR-related, not primarily inlining-related. – Angew is no longer proud of SO Apr 21 '15 at 11:55
  • 4
    @JonathanMee A compiler can detect whether a variable *is* modified. No compiler is a good enough mind-reader to detect whether a variable *should* be modified, which is why `const` exists. – molbdnilo Apr 21 '15 at 12:00
  • @Angew Wait... so where in your comment was the example of `inline` not being a ignored? Doesn't the compiler do the exact same thing with `inline`d and non-`inline`d functions? – Jonathan Mee Apr 21 '15 at 12:08
  • 4
    @JonathanMee No. If you put a function definition at namespace scope in a header, do not mark it as `inline`, and include that header in more than one source file, you'll get a linker error. You will not get that error if you *do* mark it as `inline`. – Angew is no longer proud of SO Apr 21 '15 at 12:19
  • @Angew Just checked, that is definitely not the case on Visual Studio. I don't have any other compilers on hand to check though... – Jonathan Mee Apr 21 '15 at 12:34
  • @JonathanMee I just tested with VS 2010 and it does indeed produce a linker error. I don't think *any* version of even a Microsoft linker could be so non-standard as to ignore a multiple definition error. File1: `int f() { return 42; } int main() { return f(); }`. File2: `int f() { return 42; }`. Both linked into the executable. – Angew is no longer proud of SO Apr 21 '15 at 12:41
  • @Angew Wait... it looks like what you're talking about is redefinition? How would `inline` solve that? I'm definitely seeing an error there whether or not you use `inline`. – Jonathan Mee Apr 21 '15 at 13:08
  • 3
    @JonathanMee Then you must have done something wrong. If you mark **both** the `f`s as `inline`, it must link correctly. *That* is the semantics of the `inline` keyword, and "inline functions" in C++. It allows the function to be defined in more than one translation unit (such as when you include a header with its definition). – Angew is no longer proud of SO Apr 21 '15 at 13:30
  • @Angew I still have not been able to figure out what you're doing that makes `inline` a necessary keyword. I've opened a question here: http://stackoverflow.com/q/29796264/2642059 I want to understand what you're saying, I was hoping that given the ability to answer rather than comment you could convert me to an `inline` disciple. – Jonathan Mee Apr 22 '15 at 11:36

8 Answers8

19

You don't put const as the result of not modifying a variable. You use const to enforce you not modifying it. Without const, you are allowed to modify the value. With const, the compiler will complain.

It's a matter of semantics. If the value should not be mutable, then use const, and the compiler will enforce that intention.

tenfour
  • 36,141
  • 15
  • 83
  • 142
  • 2
    I deleted my last comment; I think I know better where you're going with this. The fact that the compiler can enforce `const` is also proof that it can make the same optimizations whether or not you specified `const`. I would guess that most compilers will thus generate exactly the same code for specified `const` and non-specified-`const`-but-not-modified-anyway. – tenfour Apr 21 '15 at 12:20
  • Right that's why I referenced `inline` the compiler will `inline` functions at its discretion whether or not we ask it to. I'm saying the same for `const`. I never declare functions `inline` anymore cause the compiler knows better than I do anyway. Why would I declare variables `const`? – Jonathan Mee Apr 21 '15 at 12:38
  • 3
    You would specify `const` for the reason I said. Even if `const`-related optimizations happen whether or not you specify `const`, there are still other, better reasons to specify it. The *primary* reason to specify `const` is your intention, like I said in my answer. If you MEAN `const`, then specify `const`. – tenfour Apr 21 '15 at 12:44
  • Does that mean that `const` causes instruction overhead for the compiler? – user129393192 Jun 22 '23 at 18:20
13

Yes, the compiler can prove constness in your example.

No, it would be of no use :-).

Update: Herb Sutter dedicated one of his gotchas to the topic (http://www.gotw.ca/gotw/081.htm). Summary:

  • const helps most by making the compiler and linker choose functions for const objects including const member functions which can be coded to be more efficient.
  • const doesn't help with the usual translation unit model [differs from what I supposed]; the compiler needs to see the whole program for verifying factual constness (which the mere declaration does not guarantee) and exploiting it, as well as prove the absence of aliasing ...
  • ... and when the compiler can see the whole program and can prove factual constness it actually of course doesn't need the const declaration any longer! It can prove it. Duh.
  • The one place where const makes a big difference is a definition because the compiler may store the object in read-only memory.

The article is, of course, worth reading.

With respect to whole program optimization/translation which usually is necessary to exploit constness cf. the comments below from amdn and Angew.

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • Integrated "complinkers" have arrived, and are not unusual :-) https://gcc.gnu.org/onlinedocs/gccint/LTO-Overview.html – amdn Apr 21 '15 at 12:53
  • 1
    @amdn Thanks for the info. Integrated it in my answer. – Peter - Reinstate Monica Apr 21 '15 at 13:06
  • The VS toolchain has LTCG (link-time code generation) as well. I'd say most (if not all) modern compilers do. – Angew is no longer proud of SO Apr 21 '15 at 13:08
  • @PeterSchneider That was a phenomenal link, I'd give you another +1 if I could. After listing the possible ways that `const` could benefit code, Herb Sutter concludes with: "Even when it comes to optimization, `const` is still principally useful as a tool that lets human class designers better implement handcrafted optimizations, and less so as a tag for omniscient compilers to automatically generate better code." – Jonathan Mee Apr 21 '15 at 15:49
  • 2
    I love the gotw. But then I wonder whether a language which warrants more than a 100 usually non-trivial gotchas is fit for anybody but language lawyers. – Peter - Reinstate Monica Apr 21 '15 at 15:54
9

can't the compiler just auto-detect that this is the same as...

If by that you mean whether the compiler can detect that the variables are not modified in the second case, most likely yes. The compiler is likely to produce the same output for both code samples. However, const might help the compiler in more complex situations. But the most important point is that it keeps you from inadvertently modifying one of the variables.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • 1
    Is it possible that you could explain what a situation would be where it would not be possible for a compiler to detect that a variable is `const`? I realized that you modified that with, "complex situations." So maybe it's too difficult to identify such an occurrence, I was just hoping to see something first-hand. – Jonathan Mee Apr 21 '15 at 11:58
  • 4
    @JonathanMee Most likely different translation units. The compiler in the C/C++ compiler model (as opposed e.g. to the c# model) does not have access to the object files, even if they contained enough type information. It cannot know that a function in a different TU does not modify a param passed by ref or pointer. (The linker would, but then it's too late for code generation, unless one has multiple compile/link runs as with runtime optimization info, or an unusual, integrated "complinker"). – Peter - Reinstate Monica Apr 21 '15 at 12:11
  • 2
    @PeterSchneider That is actually the best answer I've seen so far. I would like to accept that if you could type it up as an answer, sir. – Jonathan Mee Apr 21 '15 at 12:16
9

The compiler will always know what you did and will infer internal constness from that in order to optimize the code.

What the compiler can never know is what you wanted to do.

If you wanted a variable to remain constant but accidentally change it later in the code the compiler can only trap this error if you tell the compiler what you wanted.

This is what the const keyword is for.

Galik
  • 47,303
  • 4
  • 80
  • 117
4
struct bar {
  const int* x;
};

bar make_bar(const int& x){
  return {&x};
}

std::map<int,bar> data;

shuffle(data);

knowing that bar will never modify x (or cause it to be modified) in its lifetime requires understanding every use of bar in the program, or, say, making x a pointer to const.

Even with perfect whole program optimization (which cannot exist: turing machines are not perfectly understandable), dynamic linking means you cannot know at compile time how data will be used. const is a promise, and breaking that promise (in certain contexts) can be UB. The compiler can use that UB to optimize in ways that ignores the promise being broken.

inline is not obsolete: it means the same thing it ever did, that linker collisions of this symbol are to be ignored, and it mildly suggests injecting the code into the calling scope.

const simplifies certain optimizations (which may make them possible), and enforces things on the programmer (which helps the programmer), and can change what code means (const overloading).

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
3

Maybe he could but the const statement is also for you. If you set a variable as const and try to assign a new value afterwards you will get an error. If the compiler would make a var out of it by himself this would not work.

TalkingCode
  • 13,407
  • 27
  • 102
  • 147
2

Const qualifier is a method to enforce behavior of the variables inside your scope. It only provides the compiler the means to scream at you if you try to modify them inside the scope where they are declared const.

A variable might be truly const (meaning it is writen in a read only location, hence compiler optimizations) if it's const at the time of it's declaration.

You can provide your 2nd function non const variables who will become "const" inside the function scope.

Or alternativelly you can bypass the const by casting , so the compiler cannot parse your whole code in an attempt to figure out if the valuea will be changed or not inside the function scope.

Considering that const qualifiers are mainly for code enforcing, and that compilers will generate the same code in 99% of cases if a variable is const or non const, then NO, the compiler shouldn't auto-detect constness.

MichaelCMS
  • 4,703
  • 2
  • 23
  • 29
  • This seems like the argument against `auto`. If the code is going to end up the same, *then how is const helping anything?* Why do we write it at all? – Jonathan Mee Apr 21 '15 at 12:05
  • Const is useful for enforcements of the code . In a little function such as this this might not seem like a big gain, however in a bigger context (such as classes having const functions, or accepting const paremeters) it gives a way of self documentation to the code (if a function takes a const paremeter, then the creator of that function states he will not modify that variable inside). Regarding auto : this is used to avoid to specify an obvious type (EG : if a function returns a namespace1::namespace2::namespace3::ClassA type , you would rather just say auto then putting all of those). – MichaelCMS Apr 21 '15 at 12:17
0

Short answer: because not all problems are that simple.

Longer answer: You cannot assume that an approach which works with a simple problem also works with a complex problem

Exact answer: const is an intent. The main goal of const is to prevent you doing anything accidentially. If the compiler would add const automatically it would just see that the approach is NOT const and leave it at it. Using the const keyword will raise an error instead.

Daniel
  • 1,041
  • 7
  • 13