我正在从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;
}
我试图弄清楚这是否是使用工会的合适案例,还是仍然有演员阵容,如果可以,为什么?
答案 0 :(得分:0)
如果可以正确初始化对象x
,则if
中的main()
语句将是合法的,因为尽管C ++标准的第[class.union]/1
条有以下限制:
1) 在联合中,如果非静态数据成员的名称指向其生存期已开始且尚未存在的对象,则该成员是活动的 结束了。对象的最多一个非静态数据成员 联合类型可以随时处于活动状态,即最大 可以将非静态数据成员之一存储在任何位置的联合中 时间。
以下异常允许您访问公共成员type
:
为了简化联合的使用,做出了一项特殊保证: 如果标准布局联合包含多个标准布局结构 共享一个共同的初始序列,以及非静态数据 此标准布局联合类型的对象的成员是活动的,并且 是标准版式结构之一,可以检查 任何标准布局结构成员的公共初始序列。
但是您的代码段中的问题是,您创建了一个联合对象x
却未激活其任何成员([basic.life]
/ 1.2):
(...)如果对象是联合成员或其子对象,则其 仅当该联合成员是中的初始化成员时,生命周期才开始 工会
这意味着当没有成员处于活动状态时,您直接将一些数据读入并集对象,因此仍然没有成员处于活动状态。严格遵循该标准,我知道这完全无法保证。
正确的方法是读取type
,然后将相关成员初始化为,并在其中读取其余的结构(或将所有内容读入缓冲区并按照类似策略进行复制)。但是,实际上,您的代码将在大多数编译器上运行。