Consider this snippet:
void foo(const int&);
int bar();
int test1()
{
int x = bar();
int y = x;
foo(x);
return x - y;
}
int test2()
{
const int x = bar();
const int y = x;
foo(x);
return x - y;
}
In my understanding of the standard, neither x
nor y
are allowed to be changed by foo
in test2
, whereas they could be changed by foo
in test1
(with e.g. a const_cast
to remove const
from the const int&
because the referenced objects aren't actually const in test1
).
Now, neither gcc nor clang nor MSVC seem to optimize test2
to foo(bar()); return 0;
, and I can understand that they do not want to waste optimization passes on an optimization that only rarely applies in practice.
But am I at least correct in my understanding of this situation, or am I missing some legal way for x
to be modified in test2
?
The standard says in [dcl.type.cv]:
Except that any class member declared
mutable
[…] can be modified, any attempt to modify […] a const object […] during its lifetime […] results in undefined behavior.
It is also not possible to make this defined by ending the lifetime of the object prematurely, according to [basic.life]:
Creating a new object within the storage that a const complete object with […] automatic storage duration occupies, or within the storage that such a const object used to occupy before its lifetime ended, results in undefined behavior.
This means that the optimization of x - y
to zero is valid because any attempt to modify x
in foo
would result in undefined behavior.
The interesting question is if there is a reason for not performing this optimization in existing compilers. Considering that the const object definition is local to test2
and the fact is used within the same function, usual exceptions such as support for symbol interposition do not apply here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With