Tuesday, April 27, 2010

Sometimes My Const is None of Your Business

There seems to be a relative dearth of C++ related blogs out there, at least compared to the webby world of Java and Ruby and the like. One that I have found to be consistently good is The C++ Reference Guide, though it is debatable if it can really be considered a blog. As the name implies it's a reference guide for C++, but as it is in the process of being created it has a RSS feed that gets updated as new topics are added. There's also a bit more commentary in it than one would normally expect from a reference guide. Given these two qualities I'm considering it a blog, even if that's not strictly accurate.

Now while I did say that the Guide is consistently good, I do find fault with it from time to time. The most recent case would be the following:

Declaring value arguments as const is a close relative of the first gaffe. Raise your hand if you haven't seen a hyper-corrective (yet utterly wrong) function declaration of this kind:

void doStuff(const int action_code);

Programmers who declare a value argument as const don't realize that by doing so, they expose themselves to mockery. Even if their aim is to document the fact that the function isn't allowed to modify its argument, declaring a value argument const is redundant and wrong. Remember: the const in this context applies to a local copy of the argument passed to the callee. It doesn't apply to the caller's argument. Hence, declaring value arguments as const is always a bad idea.

Bottom line: never declare value arguments as const. Although it might seem harmless, it's plain wrong, and it might suggest that you don't understand the C++ argument passing mechanism at all.

Let me start by saying that I declare const by value arguments all the time when the type being passed is a primitive like int1. Now I'm pretty sure I have a decent grasp of what it means to pass a parameter by value; I understand that when a function takes a parameter by value it is making a copy of that value for its own internal use and thus the const doesn't affect the caller's variable in any way.

So why do it? That's none of your business, at least if you're the caller of my function. If my function takes a parameter by value then I have my own copy of the value that you passed in and I can do damn well anything I please with it including declaring it const. In this case the const is not for the caller's benefit, it's for the function author's. In my experience the more stuff you can declare const the better (stuff that can't change has less chance of being stuff that can break). The only way to make that parameter value const is to declare it as such in the function's declaration. This could probably be considered a leak of information about the function's internals by the interface, but it seems like a rather innocuous one to me. Maybe I should be demanding that the C++ standard be amended so that I can have my const by value arguments without having to declare them as such in function declarations so as to avoid ridicule and mockery by the likes of the author above...

  1. Note that I do not do this with anything that is not a primitive type, I'm not a moron (as far as I know, the Dunning-Kruger effect notwithstanding). Unfortunately the code base that I work on passed through some less than stellar hands in the past and I see lots of functions that take arguments like const CString foo (note the lack of ampersand).