【问题标题】:Is using reinterpret_cast after typeid check valid?typeid 检查后使用 reinterpret_cast 是否有效?
【发布时间】:2018-05-20 13:50:07
【问题描述】:

如果我首先验证指向基类的指针是某种类型(使用typeid),是否可以对其执行reinterpret_cast 以节省一些性能?

class Base {
    virtual ~Base() {}
};
class A : Base {};
class B : Base {};
...
class Z : Base {};

后来在某处:

void fn(Base & msg) {
    const auto & tid = typeid(msg);
    if (tid == typeid(A)) {
        A * ptr = reinterpret_cast<A*>(&msg);
    } else if (tid == typeid(B)) {
        B * ptr = reinterpret_cast<B*>(&msg);
    } ...
    ...
    } else if (tid == typeid(Z)) {
        Z * ptr = reinterpret_cast<Z*>(&msg);
    }
}

据我所知,这段代码运行良好,正如我认为的那样。但是,我很好奇这仅仅是因为我很幸运,还是这实际上是定义明确的用法等等?以这种方式使用reinterpret_cast

在你说为此只使用正常的多态性之前,我无法按原样更改类,因此我需要围绕它进行构建。

【问题讨论】:

  • 这里的整个设计看起来难以置信坏了。仅仅重写你无法从头开始改变的相关内容绝对值得考虑。
  • reinterpret_cast 不考虑 vtable。您可能会丢失 RTTI 并有未定义的行为。所以不,这是无效的
  • @BaummitAugen 很乐意,但我只是在修复另一个团队的烂摊子,可悲的是,重写在预算中:/
  • @user1810087 我想知道为什么它无效......我的意思是,在typeid(*msg) == typeid(Z) 之后,我知道它最初是Z 的实例,不是吗?那么为什么用reinterpret_cast&lt;Z*&gt;(&amp;msg) 告诉编译器它是Z 的实例是无效的呢?我不明白为什么这里根本需要考虑 vtable...

标签: c++ c++11 visual-c++ visual-studio-2012


【解决方案1】:

不,行为仍然是正式的未定义的。

以这种方式使用reinterpret_cast 仍然违反严格的别名规则。

如果性能真的在这里是一个问题,那么您可能希望完全避免使用virtual 类。

【讨论】:

  • 那我就用 dynamic_cast 代替,谢谢 :)
【解决方案2】:

与 Bathsheba 的回答一样,您仍然会有未定义的行为。

但是,如果你没有虚拟继承,你可以使用static_cast,它会正确地偏移指向子类的指针:

void fn(Base & msg) {
    const auto & tid = typeid(msg);
    if (tid == typeid(A)) {
        A * ptr = static_cast<A*>(&msg);
    } else if (tid == typeid(B)) {
        B * ptr = static_cast<B*>(&msg);
    } else if (tid == typeid(Z)) {
        Z * ptr = static_cast<Z*>(&msg);
    }
}

【讨论】:

  • 是的,这应该适用于大多数情况,除非您重复了多个继承基类(例如 IUnknown)——我认为编译器会抱怨这些。
猜你喜欢
  • 1970-01-01
  • 2010-09-29
  • 1970-01-01
  • 2011-02-24
  • 2013-06-24
  • 2015-04-11
  • 1970-01-01
  • 2015-04-21
  • 2014-10-05
相关资源
最近更新 更多