I believe that the motivation is to allow the compiler to cache the values ​​of const objects (note that const objects, not just pointers to pointers to a constant and a link to a constant) and the addresses of referee links to calls to unknown code.
In your second example, the compiler can “first see” that the object was created and destroyed, and secondly, it was recreated using the same value. But the authors of the standard wanted compilers to be allowed to include this code:
struct Foo { const int & x; Foo (int & i) : x(i) {} }; int i = 1; Foo f(i); some_function_in_another_TU(&f); std::cout << fx;
In it:
struct Foo { const int & x; Foo (int & i) : x(i) {} }; int i = 1; Foo f(i); some_function_in_another_TU(&f); std::cout << i;
since the reference element f cannot be reinstalled, and therefore it must still refer to i . The destruct-and-construct operation violates the non-recoverable x reference element.
This optimization should not be particularly controversial: consider the following example using a const object, not an object with a const or reference element:
const int i = 1; some_function_in_another_TU(&i); std::cout << i;
Here i is a compile-time constant, some_function_in_another_TU cannot correctly destroy it and create another value instead of it int . Therefore, the compiler should be allowed to emit code for std::cout << 1; . The idea is that the same should be true by analogy for const objects of other types and for references.
If calling an unknown code can reinstall the reference element or change the value of the const data element, then a useful language invariant (links will never be re-closed, and constant objects will never change their values) will be violated.
Steve jessop
source share