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

时间:2018-08-24 11:53:13

标签: c++

这个问题是将字节流强制转换为非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?如果我删除了构造函数,那还好吗?

2 个答案:

答案 0 :(得分:2)

必须通过构造函数构造一个对象。您不能简单地转换一个字节流,然后假装它会导致一个可用的对象。 对于trivially copyable类型,您可以先创建对象,然后以字节为单位进行复制,但是否则需要构造函数调用。

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

答案 1 :(得分:0)

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

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

out的构造将从Data的每个元素开始就地构造in对象。并且您可以信任您的编译器以optimize away any memory copy;)