I work with C++ in an embedded environment (actually a subset of C++) and want some advice on the use of pointers/references when passing arguments to routines.
A common tip goes something like “use references when you can, and pointers when you have to”. I believe this is related to avoiding null pointers.
However, our current programming guideline prohibits the use of references.
Please refer to the discussion thread below, and see if you agree.
Bert:
We should be taking advantage of passing arguments by reference (built-in null pointer protection) when appropriate. This would yield smaller, more robust code.
Ernie:
I disagree. Using references hides what parameters might be changed and as such, when you are reviewing code or looking at what a particular function is doing, you now have to look at each and every function it calls, and each and every function they call to see if any of the parameters you are passing in might get changed.
Whereas, if you use pointers, then you know by the fact that if you are passing in a pointer, it might get changed. If you are not passing in a pointer, then you know it has not been changed.
This ease in maintenance is worth the NULL pointer issues. With references, just because you don’t have NULL pointer issues, does not mean that the object has been correctly initialized and that you have good data.
Bert:
That concern can be mitigated by labeling input parameters (references) as “const”. (This is similar to the Google coding style.) Then you know the other parameters are the ones that may be modified. The modifiable parameters can start with the “r” prefix, which was allowed in our guidelines earlier. (And don’t be surprised when tools such as Visual Assist color code inputs/outputs to help give visual cues.)
Ernie:
Labeling parameter (references) as “const” does NOT mitigate the problem. Because when you are up a level and someone is calling the function, then you have just a regular variable like “nSomeNumber”. You MUST go to the function prototype to see if that variable might get changed. Or, you MUST hover over the function to see the prototype. So you can not just quickly scan code and have an idea of what might be happening.
Also, there are times where you do not have color coding, like in Beyond Compare during a code review, and you can not easily hover or go to the prototype.
I am strongly against the use of references, as they make code maintenance and readability difficult and error prone; and the errors you get are not the simple to detect NULL pointer issues, they are logic errors where a value is set above a function and passed into the function as a reference, and then after the function is called the value is used and not having expected it to change.
Grover:
FYI, Google allows const reference for arguments. Presumably, this is to save on the cost of copying objects. Google does not allow simple reference for arguments. If an object is to change, then pass it by pointer.
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments
This is good advice, and yes, avoiding null pointers is the reason (it’s also easier to read as you don’t have to constantly dereference references, or use
->)I can understand the argument against using non-const references. In that case, Google’s style guide is the best approach (use const references for inputs, pointers for outputs). Not using const references for inputs is just madness: you either have to pass by value, which will be incredibly slow, or pass by pointer, which is going to require a hell of a lot of address taking and dereferencing (not to mention pointless null pointer checks). That would make the code far more unreadable than worrying about modified references.