3 ms·
I don't have a lot of opinions about C++ (which is good, since the number of cases covered here was quite large). For C, I really do think that const-ing all t
by unwind 5y ago
I don't have a lot of opinions about C++ (which is good, since the number of cases covered here was quite large).
For C, I really do think that const-ing all the things when possible helps, since doing so should (I don't have evidence, I'm not a CS researcher) help protect against accidental modification which can lead to dangerous bugs. More, I really think it makes the programmer's intent much more clear, which I find important especially in large and perhaps not so disciplined codebases as the article author seems to assume. Basically, in a language where all variables are modifiable by default, not consting (to me) means "I'm going to be modifying this later, watch out!".
Also for code still using C89-ish style of declaring all variables at the beginning of the scope. If you have a 150-line function with 13 lines of variables at the top, it would really make it easier to know which variables to focus on understanding if some are const and some not.
I also think it just makes the code more self-explanatory and "confident"-looking when things, even local variables that are only referenced a couple of times in the next few lines, are const.
Something like:
// Make the string one character shorter.
void truncate(char *s)
{
if (s != NULL)
{
const size_t len = strlen(s);
if (len > 0)
{
s[len - 1] = '\0';
}
}
}
This is ultra-trivial, but to me it reads much better when the 'len' is const. Sure I can see that there is only two further references to that variable, but it's just ... simpler. You could write it in a more "elite" old-sk00l C style like this:
// Make the string one character shorter.
void truncate(char *s)
{
if (s != NULL)
{
size_t len = strlen(s);
if (len-- > 0)
{
s[len] = '\0';
}
}
}
But to me that is just needless complexity. I did not Godbolt the above to see if there's any difference in the generated code, but would naively expect there not to be.
Addendum/edit: I'm still really opposed (like the article) to const:ing scalar function arguments, since I feel that leaks internal information (whether or not the code inside a function is going to change the value of an argument) to the outside which is bad. I would probably treat the value of an argument as const anyway though, it's just simpler.
- LevelAd8 5y ago2 more instructions in GodBolt for the second version, in the end the urge to look cool and "elite" more often than not causes trouble. Unless there really is a need for complexity, it's almost always better to follow KISS principle
- unwind 5y agoOkay, thanks. Obviously using post-decrement in the if like I did is a red flag of readability/complexity in many cases, and I could just have well kept the subtraction to the indexing line.
- nkurz 5y agoI saw no difference for between unwind's two versions with current GCC, clang, or icc with -O3: https://godbolt.org/z/n6avo5ovq https://godbolt.org/z/n6avo5ovq. Did you possibly forgot to use optimization? I was surprised though to see that icc inlined the call to strlen!
- bluetomcat 5y agoWith the const-everywhere approach, the code reads like it's in an SSA format and is dataflow-oriented. As an extreme example, the "len - 1" expression can be substituted with yet another const variable: const size_t len = strlen(s); if (len > 0) { const size_t len_minus_one = len - 1; s[len_minus_one] = '\0'; } The additional const "variables" also add another layer of self-documentation by virtue of their names.
- foxfluff 5y agoNot to argue your point but I think the "elite" old-sk00l C style implementation would be this: void truncate(char *s) { if (s && *s) s[strlen(s)-1] = 0; } I don't have a hard and fast rule on when to use const for locals. In bigger functions, sometimes adding a const is just a nice quick way to ask the compiler if that variable gets modified later. So it can help readability. With tiny functions, it rarely matters much, you see everything at glance anyway. That's bikeshedding territory. I tend to prefer to elide unnecessary temporary variables (then you don't need to worry whether it's const or how it should be named.. problem eliminated) and just use expressions like above. But this is also not a hard rule. In general, any hard rule smells like cults and religion.