C++中使用memcpy切换union活跃成员的相关问题
Union成员与memcpy的行为分析
假设sizeof( int ) == sizeof( float ),针对给出的代码片段,解答如下:
问题1:代码是否会导致未定义行为(UB)?
不会。std::memcpy是字节级的内存复制操作,C++标准允许通过这种方式操作对象的存储表示。这里&u.f是合法的指针(指向union的float成员),复制的字节数sizeof(u)等于两个成员的大小(因为union的大小由最大成员决定,此时两者大小相同),复制的源是&u.i指向的合法存储区域,整个操作没有违反标准的限制,不存在未定义行为。
问题2:memcpy调用后union的活跃成员是什么?
活跃成员是u.f。根据C++标准,union的活跃成员是最后被修改(包括通过字节级操作修改其存储)的成员。memcpy直接写入了u.f指向的存储区域,相当于修改了u.f的对象表示,因此f成为新的活跃成员。
问题3:若sizeof( int ) != sizeof( float ),上述两个问题的答案是什么?
关于未定义行为:
会触发未定义行为。原因是sizeof(u)等于int和float中较大的那个类型的大小。当执行memcpy(&u.f, &u.i, sizeof(u))时,源地址&u.i指向的存储区域仅为sizeof(int)字节,若sizeof(u)大于sizeof(int),则复制操作会读取超出u.i对象存储范围的内存,这属于越界访问,违反了C++标准中对象存储访问的规则,导致未定义行为。
关于活跃成员:
由于已经触发未定义行为,谈论活跃成员没有意义——未定义行为下程序的任何行为都不受标准约束,无法确定活跃成员的状态。
内容的提问来源于stack exchange,提问作者cerveka2
相关产品推荐
相关产品推荐

