ar2015
ar2015

Reputation: 6130

c++ pass single variable as both reference and const reference

Let's assume there is a function f which receives two variables one by reference and another is a constant reference.

If I pass a single variable as both arguments an error occurs:

result:

a: 6
b: 6

code

void f(int &a,const int &b)
{
    a=a+1;
    std::cout<<"a: "<<a<<"\n";
    std::cout<<"b: "<<b<<"\n";
}

int main()
{
    int m=5;
    f(m,m);
    return 0;
}

Does this problem have any known name? Also, is there any way to warn compiler to be careful about that?

Upvotes: 2

Views: 235

Answers (2)

M.M
M.M

Reputation: 141544

This code is well-defined and there is no problem.

The code const int &b means that:

  • b refers to an int
  • The expression b may not be used to modify that int.

However it is perfectly fine for the int to be modified by other means. For example, via a here. When compiling f, the compiler must take into account that a and b might both refer to the same object.


Some compilers have extensions to specify that function parameters (or other variables) should not alias; e.g. in MSVC++ 2015 you can write:

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

and then the compiler may compile f assuming that &a != &b, i.e. it might output 6 5 for your code, which would now be silent undefined behaviour -- the compiler isn't required to diagnose violations of __restrict


When writing a function that takes multiple reference or pointer parameters of the same type (excluding qualifications), or char, you must be aware that it's possible some parameters will alias the other parameters. You could hand this by one of the following:

  • Write your code so that it works even if the parameters alias
  • Include a check like if ( &a == &b ) return;
  • Use __restrict and document that the onus is on the caller to not alias.

A common case this shows up is the overloaded operator= for a class. This function needs to support someone writing x = x; , i.e. *this may alias the function parameter. Sometimes people solve this by checking if ( &a == this ) return;, and sometimes they omit that check but design the implementation so that it still works even if those were equal.

Upvotes: 5

geipel
geipel

Reputation: 405

This appears to be working "correctly".

You've defined the function to take two arguments. The first argument is declared to indicate that the referenced integer a may be changed in f(), but b should not be changed.

Both arguments are passed by reference and you violate the use of const because the changing a is also referenced as b.

This behavior is what I'd expect without optimization. (The integer value that is actually stored as m was incremented before the output was generated.) However, such aliasing may be treated differently depending on the compiler and options. Its behavior is likely undefined in the general case.

Upvotes: 3

Related Questions