这是使用 union 还是 reinterpret_cast 的合适案例

Is this an appropiate case to use union vs reinterpret_cast

我正在从 io 设备接收四个字(32 位)的数据。消息中的第一个词告诉我传入的数据是什么。我想知道这是否是使用 union 或 reinterpret_cast 的情况。

这是我的用例...

struct Plain {
  uint32_t  type;
  uint32_t data1;
  uint32_t data2;
  uint32_t data3;
}
struct Special1 {
  uint32_t  type;
  uint32_t data1;
  float    data2;
  uint32_t data3;
}

struct Special2 {
  uint32_t  type;
  uint32_t data1;
  float    data2;
  uint16_t data3;
  uint16_t data4;
}
union My_union {
  Plain    p1;
  Special1 p2;
  Special2 p3;

}
void foo(const Special1& x);
void foo(const Special2& x);
int main() {
  My_union x;
  read(&x.p1, sizeof(Plain)); // read from an IO device
  if(x.p1.type == 1)
  {
    foo(x.p2);
  }
  else
  {
    foo(x.p3);
  }
  return 0;
}

我想弄清楚这是否是使用联合的合适案例,或者仍然是强制转换的方法,如果是的话,为什么?

如果对象 x 被正确初始化,main() 中的 if 语句将是合法的,因为尽管 C++ 的子句 [class.union]/1 中有以下限制标准:

1) In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended. At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

以下异常允许您访问公共成员 type

One special guarantee is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout structs that share a common initial sequence, and if a non-static data member of an object of this standard-layout union type is active and is one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of the standard-layout struct members.

但是你的代码片段中的问题是你创建了一个联合对象 x 而没有激活它的任何成员 ([basic.life]/1.2):

(...) if the object is a union member or subobject thereof, its lifetime only begins if that union member is the initialized member in the union

这意味着当没有成员处于活动状态时,您直接将一些数据读入联合对象,因此仍然没有成员处于活动状态。严格按照标准,我明白这根本不能保证有效。

正确的方法是读取 type,然后初始化相关成员并读取结构的其余部分(或者将所有内容读入缓冲区并按照类似的策略进行复制).但是,实际上,您的代码将适用于大多数编译器。