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
ftakes two reference arguments:int const& aandint& b. Therefore,fis supposed not to modifya, but it can modifyb, and indeed it does. - However, in
main, I pass the same variable, referenced both byaand byb. Asfmodifiesb, 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?