Note:
Unions
do not exist for the sole purpose of type punning.Unions
exist because sometimes you want to store one type of object and later retrieve it, and sometimes you want to store a different type of object and later retrieve it.
So,Unions
original purpose was to save space when you want to be able to be able to represent different types, what we call avariant
type seeBoost.Variant
as a good example of this.
However, To re-iterate, type-punning through unions is perfectly fine in C (but not in C++, it’s unclear). In contrast, using pointer casts to do so violates C99 strict aliasing and is problematic because different types may have different alignment requirements and you could raise a SIGBUS(未对齐的数据访问) if you do it wrong. With unions, this is never a problem.
In addition, character type (
char
,signed char
, andunsigned char
) is allowed to alias anything.
In the cases that
void *
would be used, the programmer should already know correct type to cast; no type punning occurs since the original data type is used (i.e. int * -> void * -> int *)
In C++, using memcpy
should generate identical code and is does not break optimizations and well defined behavior:
double d = 0.1;
std::int64_t n;
std::memcpy(&n, &d, sizeof(d));
instead of this:
union u1
{
std::int64_t n;
double d ;
} ;
u1 u ;
u.d = d ;
- https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8
- https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
关于指针默认构造函数:
I know some POD variables are initialized by default, but others are not. (POD types include int, float, pointers, unions, arrays of POD types, structs of POD types, etc.)
How does scope and storage class affect default initialization of POD types?
Specifically, which of the following will be initialized implicitly:
Local variables with automatic storage
Static local variables
Static global variables
External variables
Variables allocated with new
POD members of a class (without explicit initialization in a constructor)
一个类成员指针,如果没有被显示初始化,其值是不确定的,如果希望被初始化,可以这样:
可以查看 std::unique_ptr/shared_ptr 的源码,其指针是如何被默认初始化为null的。
struct A { int* m; }; // POD
A* a= new A; // 成员 m 为不确定值
A* b= new A(); // 成员变量 m 会被初始化为 null; 注意必须加上()
After the call to a constructor for class X has completed, if a member of X is neither specified in the constructor’s mem-initializers, nor default-initialized, nor value-initialized, nor given a value during execution of the body of the constructor, the member has indeterminate value.