Can the compiler not determine whether a variable is const by Itself?
Asked Answered
H

8

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?

Horta answered 21/4, 2015 at 11:37 Comment(20)
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.Ranged
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.Uroscopy
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.Unmentionable
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.Thirty
inline is far from obsolete. It allows for multiple definitions of the function to exist in the program without violating ODR.Harryharsh
there's also more reasons why you wouldn't like it to automatically "detect" something to be a "const", somewhat related; #456018Pimp
@Angew 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?Horta
@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.Harryharsh
@PeterSchneider I think that's my question then, why do we still qualify variables then?Horta
@Angew Can you give me an example? I am only aware of inline being used in reference to functions/methods.Horta
@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.Horta
@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.Harryharsh
@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.Hodges
@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 inlined and non-inlined functions?Horta
@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.Harryharsh
@Angew Just checked, that is definitely not the case on Visual Studio. I don't have any other compilers on hand to check though...Horta
@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.Harryharsh
@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.Horta
@JonathanMee Then you must have done something wrong. If you mark both the fs 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).Harryharsh
@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: https://mcmap.net/q/234810/-is-there-still-a-use-for-inline-duplicate/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.Horta
T
14

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.

Thirty answered 21/4, 2015 at 12:39 Comment(5)
Integrated "complinkers" have arrived, and are not unusual :-) gcc.gnu.org/onlinedocs/gccint/LTO-Overview.htmlOmnivore
@Omnivore Thanks for the info. Integrated it in my answer.Thirty
The VS toolchain has LTCG (link-time code generation) as well. I'd say most (if not all) modern compilers do.Harryharsh
@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."Horta
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.Thirty
A
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.

Alderson answered 21/4, 2015 at 11:43 Comment(4)
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.Alderson
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?Horta
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.Alderson
Does that mean that const causes instruction overhead for the compiler?Chivalrous
T
14

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.

Thirty answered 21/4, 2015 at 12:39 Comment(5)
Integrated "complinkers" have arrived, and are not unusual :-) gcc.gnu.org/onlinedocs/gccint/LTO-Overview.htmlOmnivore
@Omnivore Thanks for the info. Integrated it in my answer.Thirty
The VS toolchain has LTCG (link-time code generation) as well. I'd say most (if not all) modern compilers do.Harryharsh
@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."Horta
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.Thirty
S
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.

Sportswoman answered 21/4, 2015 at 11:41 Comment(3)
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.Horta
@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").Thirty
@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.Horta
U
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.

Uroscopy answered 21/4, 2015 at 12:3 Comment(0)
M
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).

Marxmarxian answered 21/4, 2015 at 12:18 Comment(0)
A
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.

Annatto answered 21/4, 2015 at 11:42 Comment(0)
A
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.

Americanize answered 21/4, 2015 at 11:47 Comment(2)
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?Horta
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).Americanize
S
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.

Stanfill answered 21/4, 2015 at 11:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.