这是使用工会vs reinterpret_cast的适当案例

时间:2019-04-04 19:26:46

标签: c++ unions

我正在从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;
}

我试图弄清楚这是否是使用工会的合适案例,还是仍然有演员阵容,如果可以,为什么?

1 个答案:

答案 0 :(得分:0)

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

  

1) 在联合中,如果非静态数据成员的名称指向其生存期已开始且尚未存在的对象,则该成员是活动的   结束了。对象的最多一个非静态数据成员   联合类型可以随时处于活动状态,即最大   可以将非静态数据成员之一存储在任何位置的联合中   时间。

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

  

为了简化联合的使用,做出了一项特殊保证:   如果标准布局联合包含多个标准布局结构   共享一个共同的初始序列,以及非静态数据   此标准布局联合类型的对象的成员是活动的,并且   是标准版式结构之一,可以检查   任何标准布局结构成员的公共初始序列。

但是您的代码段中的问题是,您创建了一个联合对象x却未激活其任何成员([basic.life] / 1.2):

  

(...)如果对象是联合成员或其子对象,则其   仅当该联合成员是中的初始化成员时,生命周期才开始   工会

这意味着当没有成员处于活动状态时,您直接将一些数据读入并集对象,因此仍然没有成员处于活动状态。严格遵循该标准,我知道这完全无法保证。

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