Type punning in C++ is not like C. As per the C++ standard, one cannot use unions to convert the bit type. A discussion about this can be found here. In C++, a union is supposed to only hold one type at a time. It's intended to be used only as std::variant. Switching types is undefined behavior.
In fact, C++20 has a special casting function, called bit_cast that solved this problem.
Why has it been working so far? Because some compilers tolerate using unions and switching types, like gcc.
One important thing to mention is that performance is generally not affected by that memcpy. Compilers are smart enough to convert that to a memory cast when possible. But we have to do it the right way, otherwise, it's jut undefined behavior that depends on the compiler.
Note that @practicalswift verified that the bytecode generated by clang++ -O1 is identical before and after the change: https://github.com/bitcoin/bitcoin/pull/18167#issuecomment-587488632
This is a backport of Core PR18167