In practice there is very little difference and you're effectively entering the realm of UB as soon as the program starts, because through inlining and propagation a possible UB may be leveraged before the UB is sequentially hit.
When people say "just fix this in compilers, don't compile when they run into UB" it's a fundamental misunderstanding of the problem. Yes, in some cases the compiler can prove UB, and uses it to write optimiations, but it doesn't prove that all code is not invoking UB.
No kidding! There is one right here:
> Yes, in some cases the compiler can prove UB, and uses it to write optimiation
Compilers do not prove UB , on the contrary they postulate no-UB and then use this axiom to prove other properties of the code.
I think it's still a (cause of) misunderstanding. For the compiler, UBs are situations which axiomatically can not occur. "This is UB" is not a concept, because the compiler assumes at all point that UBs can not occur.
The compiler doesn't go "oh you're dereferencing a pointer which may be null, fuck you", it goes "you're dereferencing a pointer so it can't be null, and thus I can remove anything assuming possible nullability".
:) This is what I'm trying to say.
How is a compiler supposed to reject this for undefined behavior? It'd be absurd to demand the compiler someone knows all possible usages for get_value to find if any of them pass a nullptr, so what is it supposed to do?
And this is why the spec says things like that deref'ing a null pointer is undefined behavior, so that the compiler can take that function and do the thing you'd expect it to do and transform it into a simple memory read.