Reputation: 6130
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
Reputation: 141544
This code is well-defined and there is no problem.
The code const int &b
means that:
b
refers to an int
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:
if ( &a == &b ) return;
__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
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