Modifying const reference argument via non-const reference argument

However, in main, I pass the same variable, referenced both by a and by b. As f modifies b, it also modifies a, which it supposedly shouldn't

When f modifies what b refers to, it does not modify a. It modifies what a refers to, but that is okay since b is not const. It's only when you try to modify what a refers to by using a that you have issues.

Can we really say the above code is const-correct?

Yes. You do not modify a const variable.

Other than being confusing to a reader, can the above code be the source of technical problems? Such as undefined behavior, or the compiler performing wrong simplifying assumptions?

No, your code is legal and will produce the same results on all conforming compilers.


A constant reference parameter does not make the thing that it refers to const if it was not const to begin with. All it does it stop you from using the reference to modify the object. Another pointer or reference to that object can still mutate it, as long as it is not const itself.


From the API perspective of

void f(int const& a, int& b), 

f promises not to modify anything via the a reference, thus respecting const correctness on a. It moreover informs the user that b, on the other hand, is very likely to be used to modify the object which it addresses; b would likely be documented as an [in, out] parameter, or just an [out] parameter, to f. If b is in fact never used to modify the object which it addresses, and moreover have no other design reason to be a non-const reference, that, on the other hand, could arguably be a (weaker) violation of const correctness by the implementer of f.

How a user makes uses or mis-uses this API is out of scope for f itself to directly worry about, particularly once its API design choice has been made. Any user-facing API should, however, arguably be designed as to minimize (given its design constraints) the risk of a user shooting him-/herself in the foot. E.g. in this case, a value semantics approach int f(int const& a) or int f(int copy_in_a) could be used to construct a different and harder-to-abuse interface towards the user.


Yes, the code is const-correct and, no, this particular code not have undefined behavior. What you wrote here is a simple case of reference aliasing, which boils down to pointer aliasing under the hood.

That being said, aliasing like this is generally undesirable, since it is, indeed, more complicated to reason about for both the programmer and the compiler. Also, this prevents certain optimizations, especially dealing with blocks of memory.


This is indeed a bad practice, because many programmers will (incorrectly) assume that the value of int const& a is indeed constant during the call. Consider

void f(int const& a, int& b)
{
  b = a+1;
  if(something) b = a+2;
}

It will be quite surprising to see b get the value of a+3, yet this is what can happen if a and b point to the same variable.