Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying const reference argument via non-const reference argument

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 and int& b. Therefore, f is supposed not to modify a, but it can modify b, and indeed it does.
  • 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

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?
like image 224
Gabriele Buondonno Avatar asked Jun 15 '20 14:06

Gabriele Buondonno


People also ask

Can you modify const reference?

But const (int&) is a reference int& that is const , meaning that the reference itself cannot be modified.

Can a const reference be bound to a non const object?

No. A reference is simply an alias for an existing object. const is enforced by the compiler; it simply checks that you don't attempt to modify the object through the reference r .

Can a reference parameter be modified?

Yes, that is the correct way to declare a reference argument. And yes, you can modify objects through a reference.

Can we declare a non reference function argument const?

It cannot hurt to declare it const if you know that your function needs not modify its value during execution.


1 Answers

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.

like image 50
NathanOliver Avatar answered Sep 19 '22 13:09

NathanOliver