reinterpret_cast<constchar*>任何以char[size]成员开头的结构是否安全?

假设我有两个不同的结构:

struct A {
    char a_name[512];
    ...              // A struct data
}

struct B {
    char b_name[256];
    ...              // B struct data
}

鉴于std::string name,我需要检查容器中是否存在对象(无论是它A还是B)。由于这两个AB一个开始char[size]这是我在寻找比较名成员,我试过如下:

// T is a template parameter which is always an object of type A or B
           ? 
for (const T& item : container)
    if (name == reinterpret_cast<const char*>(&item))

它确实按预期工作。我读取对象就好像它是一个字符数组,但是由于A.a_name并且B.b_name保证以空值终止,我没有阅读我不应该阅读的内容......还是我?上面的代码会产生未定义的行为吗?它会产生任何我没有考虑的错误吗?如果是这样,我该如何处理这项任务?

我无法修改AB。我选择不过载操作符==对于每个类,因为AB实际上是具有予上述该结构(有更多的不同结构char[size]+更多的数据)。

回答

如果您的类是标准布局类,您的代码应该是安全的。

在 [class.members] 部分的末尾,我们有

如果标准布局类对象具有任何非静态数据成员,并且该成员不是位字段,则其地址与其第一个非静态数据成员的地址相同。... [注意:对象及其第一个子对象是指针可相互转换的]

关于复合类型的部分,[basic.compound],说

如果两个对象是指针可互转换的,则它们具有相同的地址,并且可以通过 reinterpret_cast 从指向另一个的指针获取指向一个的指针。

但是,您可以reinterpret_cast通过创建一个辅助函数来返回正确的字段来完全摆脱。

const char *GetName(const A &a) {
    return a.a_name;
}

const char *GetName(const B &b) {
    return b.b_name;
}
// ...
for (const T& item : container)
    if (name == GetName(item))

这方面有多种变体,包括GetName开始一个返回特定字段的模板函数,以及具有不同字段名称的类型的特定实现。


以上是reinterpret_cast&lt;constchar*&gt;任何以char[size]成员开头的结构是否安全?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>