规避旧版代码的RTTI [英] Circumventing RTTI on legacy code

查看:73
本文介绍了规避旧版代码的RTTI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找解决动态类型转换检查缓慢问题的方法。在您开始说我应该重新设计一切之前,让我通知您设计是在5年前决定的。我无法修复之后的所有40万行代码(我希望可以),但是我可以进行一些更改。我已经对类型标识进行了这个小测试:

I have been looking for a way to get around the slowness of the dynamic cast type checking. Before you start saying I should redesign everything, let me inform you that the design was decided on 5 years ago. I can't fix all 400,000 lines of code that came after (I wish I could), but I can make some changes. I have run this little test on type identification:

#include <iostream>
#include <typeinfo>
#include <stdint.h>
#include <ctime>

using namespace std;

#define ADD_TYPE_ID \
    static intptr_t type() { return reinterpret_cast<intptr_t>(&type); }\
    virtual intptr_t getType() { return type(); }

struct Base
{
    ADD_TYPE_ID;
};

template <typename T>
struct Derived : public Base
{
    ADD_TYPE_ID;
};

int main()
{
    Base* b = new Derived<int>();
    cout << "Correct Type: " << (b->getType() == Derived<int>::type()) << endl; // true
    cout << "Template Type: " << (b->getType() == Derived<float>::type()) << endl; // false
    cout << "Base Type: " << (b->getType() == Base::type()) << endl; // false

    clock_t begin = clock();
    {
        for (size_t i = 0; i < 100000000; i++)
        {
            if (b->getType() == Derived<int>::type())
                Derived <int>* d = static_cast<Derived<int>*> (b);
        }
    }
    clock_t end = clock();
    double elapsed = double(end - begin) / CLOCKS_PER_SEC;

    cout << "Type elapsed: " << elapsed << endl;

    begin = clock();
    {
        for (size_t i = 0; i < 100000000; i++)
        {
            Derived<int>* d = dynamic_cast<Derived<int>*>(b);
            if (d);
        }
    }
    end = clock();
    elapsed = double(end - begin) / CLOCKS_PER_SEC;

    cout << "Type elapsed: " << elapsed << endl;

    begin = clock();
    {
        for (size_t i = 0; i < 100000000; i++)
        {
            Derived<int>* d = dynamic_cast<Derived<int>*>(b);
            if ( typeid(d) == typeid(Derived<int>*) )
                static_cast<Derived<int>*> (b);
        }
    }
    end = clock();
    elapsed = double(end - begin) / CLOCKS_PER_SEC;

    cout << "Type elapsed: " << elapsed << endl;

   return 0;
}

似乎使用类ID(上面的第一次解决方案)是在运行时进行类型检查的最快方法。
这会导致线程问题吗?有没有更好的方法可以在运行时检查类型(没有太多重构)?

It seems that using the class id (first times solution above) would be the fastest way to do type-checking at runtime. Will this cause any problems with threading? Is there a better way to check for types at runtime (with not much re-factoring)?

编辑:可能我还要补充一点需要与TI编译器一起使用,目前仅支持'03

Might I also add that this needs to work with the TI compilers, which currently only support up to '03

推荐答案

首先,请注意,两者之间存在很大差异在 dynamic_cast 和RTTI之间:强制转换告诉您是否可以将基础对象视为 some 进一步派生的对象,但不一定是最衍生的对象。 RTTI会告诉您最精确的派生类型。自然,前者功能更强大且更昂贵。

First off, note that there's a big difference between dynamic_cast and RTTI: The cast tells you whether you can treat a base object as some further derived, but not necessarily most-derived object. RTTI tells you the precise most-derived type. Naturally the former is more powerful and more expensive.

因此,如果您具有多态层次结构,则可以通过两种自然方式选择类型。它们是不同的;

So then, there are two natural ways you can select on types if you have a polymorphic hierarchy. They're different; use the one that actually applies.

void method1(Base * p)
{
    if (Derived * q = dynamic_cast<Derived *>(p))
    {
        // use q
    }
}

void method2(Base * p)
{
    if (typeid(*p) == typeid(Derived))
    {
        auto * q = static_cast<Derived *>(p);

        // use q
    }
}

还要注意,如果基类是虚拟基类,则方法2通常不可用。如果您的类不是多态的,则这两种方法都不适用。

Note also that method 2 is not generally available if the base class is a virtual base. Neither method applies if your classes are not polymorphic.

在快速测试中,我发现方法2明显比基于手动ID的解决方案要快得多,而基于ID的手动解决方案则更快比动态转换解决方案(方法1)更重要。

In a quick test I found method 2 to be significantly faster than your manual ID-based solution, which in turn is faster than the dynamic cast solution (method 1).

这篇关于规避旧版代码的RTTI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆