从基本类型转换为非 POD 结构

Casting from basic type to non-POD struct

本文关键字:POD 结构 类型转换      更新时间:2023-10-16

这个问题是将字节流转换为非 POD 结构是否是未定义的行为。

在这样的地方生成数据的地方,即将 4 个 4 位值打包到一个short中。

std::vector<unsigned short> v(50);
for(int i<0; k < 50; k++)
{
v[k] = (k%8) | (k+1)%8 << 4 | (k+2)%8 << 8 | (k+2)%8 << 12
}

然后将数据作为字节流传递到第二个模块,并在接收模块中解析。

struct Data
{
Data(unsigned short a, unsigned short b, unsigned short c, unsigned short d)
{
value = (a & 0xF) | (b & 0xF) << 4 | (c & 0xF) << 8 | (d & 0xF) << 12
}
Data(unsigned short v) : value(v) {}
short getA() const
{
return value & 0xF
}
short getB() const
{
return (value >> 4) & 0xF
}
short getC() const
{
return (value >> 8) & 0xF
}
short getD() const
{
return (value >> 12) & 0xF
}
private:
unsigned short value;
}

unsigned char* data = ...;
Data* ptr = reinterpret_cast<Data*>(data);
ptr[0].getA();

这是未定义的行为吗?struct Data的大小与short相同,但是构造函数和成员函数的存在是否使它成为UB?如果我删除构造函数,它会没问题吗?

你必须通过构造函数来构造一个对象。您不能简单地强制转换字节流,然后假装它会产生一个可用的对象。 对于简单可复制的类型,您可以先创建对象,然后以字节为单位复制,否则需要构造函数调用。

回答你的问题:是的,那就是UB。

是的。但是你可以找到一个简单的替代方案:

std::vector<unsigned short> in(50);
std::vector<Data> out{begin(in), end(in)};
(void) out[0].getA();

out的构造将从in的每个元素就地构造Data对象。您可以信任编译器来优化任何内存副本;)