Consider the following code:
#include <iostream>
void f(int const& a, int& b)
{
b = a+1;
}
int main() {
int c=2;
f(c,c);
std::cout << c << std::endl;
}
- Function
f
takes two reference arguments:int const& a
andint& b
. Therefore,f
is supposed not to modifya
, but it can modifyb
, and indeed it does. - However, in
main
, I pass the same variable, referenced both bya
and byb
. Asf
modifiesb
, it also modifiesa
, which it supposedly shouldn't
This code compiles without any warning and prints 3
. If we track each variable individually, it looks like const-correctness is respected: c
is non-const, therefore it is perfectly fine to pass it as a const
ref as a
, and also as a non-const ref as b
, and within the body of f
we modify b
, which is non-const, while not touching a
, which is const. However, when c
is employed both as a
and as b
, a
is modified within the body of f
, violating the assumption that a
is const, even though no explicit const_cast
was ever called.
I made this example as simple as I could, but one can easily think of not-so-obvious use cases (such as a const
method acting on a non-const reference argument).
My question is:
- Can we really say the above code is const-correct?
- Is the above use case a known pattern? Is it considered bad practice?
- 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?