3

假设有两个结构 A 和 B。它们有一个共同的结构 C。我想知道将 reinterpret_cast 调用到 A 或 B 到 C 是否安全。如果不是,有什么方法可以在不影响性能的情况下这样做?

struct C
{
    string m_c1;
    int32_t m_c2;
    double m_c3;
    string m_c4;
};

struct A
{
    C m_a1;
    string m_a2;
    int32_t m_a3;
};

struct B
{
    C m_b1;
    string m_b2;
    int32_t m_b3;
    double m_b4;
};
int main(int argc,char *argv[])
{
        A a;
        a.m_a1.m_c1="A";
        a.m_a1.m_c4="AA";

        B b;
        b.m_b1.m_c1="B";
        b.m_b1.m_c4="BB";

        C* pc = reinterpret_cast<C*>(&a);
        cout << pc->m_c1 << " " << pc->m_c4 << endl;

        pc = reinterpret_cast<C*>(&b);
        cout << pc->m_c1 << " " << pc->m_c4 << endl;

        return 1;
}
4

2 回答 2

3

正如 Mike DeSimone 指出的那样,string不能保证类是standard-layout类,因此类C不是standard-layout,这意味着您根本无法保证内存布局。所以不安全。只有将字符串更改为 a(const) char*才能保证安全。

即便如此,只要类的布局保持不变(您不能更改成员的顺序或更改它们的访问说明符),并且类保持没有任何 vtable,这才是“安全的”一种编译器将生成显示您想要的行为的代码的方式。

这就是软件开发人员很少能够提供的两种保证。像这样写的代码也很难理解。另一个开发人员(或一个月后的同一开发人员)可能会忽略此代码(或根本不理解它),并进行所需的更改,然后代码突然损坏,您手头上出现了一些难以捕捉的错误。

A并且B是允许访问 a C(或 的某些成员C)的类。更具可读性因此更安全的解决方案是:

  • 为两者创建一个访问器AB,这可能会被内联并且不会导致性能损失。
  • 如果有任何继承原因,请使用简单继承。要么Aand B is-a ClassThatHasAC要么Aand B is-a C只要没有虚函数,您可能也不会在这里看到任何性能问题。在这两种情况下,访问器可能会为您提供好处,而无需任何性能成本。

首先创建一些简单易读的代码,并衡量性能。如果这个 C 访问成本太高,请优化。但是,如果您的优化归结为重新解释演员表技巧,请确保周围有很多警告标志,以确保没有人踏上这个诱杀陷阱。

于 2013-01-03T07:38:27.720 回答
2

为什么不从 C 继承 A、B 并使用它static_cast呢?应该更安全/更清洁。

事实上,在你的情况下,你根本不需要演员,你应该能够将 A 或 B ptrs 分配给C*

于 2013-01-03T07:06:23.957 回答