Monday 15 October 2018

C++: To Reference or Not

Constant Something Reference or Something constant reference... I ask myself this in a similar manner as Prince Hamlet at the start of the nunnery scene... For as a C++ programmer and English speaker I've always found myself most comfortable using the phraseology thus:

const int X (0);

And to pass this to a function:

void foo (const int& p_X);

I find this most useful, we're passing a constant integer reference to the function... However, I was recently challenged that this meant something else to a reader, her input was that it meant "constant integer" reference, that is we would ONLY be able to pass "const int" instances, not "int" instances.   The thinking being:

const int X(0);
void foo(const int& p_X);

foo(X);

Would compile, whilst:

int Y(42)
void bar (const int& p_Y);

bar (Y);

Would fail to compile or at least spit out a warning because "int" was not able to be passed into the function as "constant integer" and "integer" to this reader were different types.

They're not really of course, constant is a decorator (and one which we can remove with const_cast) the aim of using "const int reference" as the type is not all of our purpose in declaring the function like so, the purpose is to communicate what we do with the value going into the function.

It is 100% not about stopping Y being passable into the function as above.

No, we want to tell any user of our code that within the functions "foo" and "bar" we do not change the value, if they pass Y to us with 42, when the function is complete Y will stil contain 42.  If the value could potentially change we would not be able to use "const" that's the purpose of passing const in this case.

Passing by reference is just to save us the time, effort and delay in allocating memory and taking a copy of the parameter before moving into the body of the function, so:

void bar (const int p_Y)

Would be the same operation as above, we tell the user we don't change the value of the parameter, but we do because we take a copy of the value being passed in and operate upon it.

The communication we get with this is very useful.

But of course, if we're using threaded programming and we pass a reference to a value at time point A, then sometime later elsewhere edit the referenced value, we may run into unexpected behaviour, so there is an argument sometimes to take a copy at the point of instantiating the child function, in the most part however, passing by reference is considered the norm.

No comments:

Post a Comment