Needed: Const Policy

Started by
5 comments, last by Bregma 6 years, 11 months ago

I am just finishing up on a project that is an 'asteroids' type game. My question is how I should use const. I did not use it very much at all just in some set member functions really. I did a little research and wanted to know if someone could just instruct me on a policy for using it.

Thank you; I am appreciative,

Josheir

Advertisement

Either

A) Don't bother.

B) Use it whenever something is not meant to be changed (i.e. be constant).

B) is trickier than A), but can help catch unwanted bugs, and can also potentially help the compiler.

Hello to all my stalkers.

Thank you Lactose,

Josheir

Just a notice in advance: all this kind of stuff will always be opinion-biased (though this I'd say is an easier one).

My short version: use const one every variable and member function whenever you can, as long as you don't need const_cast and mutable to do so, but be consistent in the scenarios where you apply it.

Long version: const is mostly just a communication to any other programmer in the sense of "I will not modify this variable" or "this member function will not change the state of the object". In the end, they could be false, as you can circumvent both 'promises' with const_cast and mutable members, so for this reason here's little compilers actually optimising for the case afaik (i.e. it's quite unlikely to make a performance difference).

I consider that communication to the programmer of great use. If a function accepts some object by reference, it's good if it's marked const so that I know it will (probably) not modify it. In fact if it's not marked const, I tend to the function will modify it (hence I'd advise to at least always use this for those passed by reference). If a member function is marked const, I know it will (probably and hopefully) not modify the object's state, making it easier to follow.

No less applies to local variables. If it is marked const at its declaration, I know it will not be modified, which can be a good-to-know if some local variable is passed into a function, since you can't see on first eye whether that function accepted it by reference, possibly modifying the variable in the process. I know that's not a possibility if it was marked const in the first place, since that reference has to be a const reference for it to compile. Of course, with descriptive names having to know this can be unnecessary in the first place, so I wouldn't worry too much about this.

I'd primarily get in the habit of using const references for parameters and marking member functions const. Marking non-reference parameters const is not so much of an issue, as they don't change anything for the side of the caller as the value is copied anyway. Adding const in other situations doesn't do much harm, but I'd be careful to be consistent so that later you don't have to figure out why something wasn't marked const (I speak from experience). Marking half your local variables const and the other half not, even though they are not changed either, is arguably worse to read.

Primarily I use const on reference and pointer types whenever the pointed-at object should not be modified. I find that this means that most references/pointers actually involve the const keyword (which begs the question of why is const opt-in rather than opt-out?).

This practice is most important around function boundaries: Marking params and return-values as const when they are references/pointers. Unless of course you actually do need to modify them. Marking local references/pointers as const is good too though.

You will quickly find that you also need to mark read-only member functions as const, since the compiler will only allow you to invoke const member functions through a const reference/pointer.

For types with value semantics I tend not to bother marking them as const, I tend not to find much benefit from that since they get passed as copies anyway.

Agreeing with those above. It usually needs to be an either/or decision across your entire code base. Either everything is const-correct, or nothing is.

Const is 'viral'. As you start adding them, the functions they call also need to be marked as const. Their calls also need to be const. Repeat all through the code base. As you start adding const you end up requiring them in far more places than you might have expected. Sometimes they become awkward, but in those cases you know you are violating good practices within the code base. If you cast away constness that is a code smell that you're probably doing things wrong.

Deciding to leave them out generally means removing them from the code base when they are discovered. As the code grows any pesky const elements will be discovered and eliminated.

The standard libraries are written to work either way, but many third-party libraries favor one way or the other. In those cases you'll need to write appropriate shims, either to make things const or to cast away constness.

... and if you would like a reasoned, documented policy to help you make your decision, you could do worse than to follow the C++ Core Guidelines on the subject, developed by the same people who develop the language and its compilers.

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement