什么更快:从虚拟基础或交叉投射向下投射?

时间:2011-08-04 11:45:56

标签: c++ dynamic-cast visitor downcast cross-cast

这有点假设,因为我并不太担心性能 - 只是想知道哪个选项实际上是最快/最有效的,或者没有任何差别。

假设我有一个支持重载的访问者模板的以下代码:

#define IMPLEMENT_VISITOR_WITH_SUPERCLASS(superclass)  \
    typedef superclass visitor_super_t;     \
    virtual void visit(Visitor& v) { v.visit(*this); }
//-----------------------------------------------------------------------------
// Implementation detail:
// Selective dispatcher for the visitor - required to handle overloading.
//
template <typename T>
struct VisitorDispatch {
    static void dispatch(Visitor* v, T* t) { v->visit(*t); }
};
// Specalization for cases where dispatch is not defined
template <> struct VisitorDispatch<void> {
    static void dispatch(Visitor* v, void* t) { throw std::bad_cast(""); }
};

//-----------------------------------------------------------------------------
// Derive visitors from this and 'Visitor'.
template <typename T>
class VTarget
{
public:
    // Don't really need a virtual dtor.
    virtual void dispatch(T& t) = 0;
};

//-----------------------------------------------------------------------------
class Visitor
{
public:
    virtual ~Visitor() = 0;

    template <typename T>
    void visit(T& t) {
        typedef VTarget<T> target_t;
        target_t* tgt = dynamic_cast<target_t*>(this);
        if (tgt) {
            tgt->dispatch(t);
        }
        else {
            // Navigate up inhertiance hierarchy.
            // requires 'super' to be defined in all classes in hierarchy
            // applicable to this visitor.
            typedef typename T::visitor_super_t super;
            super* s = static_cast<super*>(&t);
            VisitorDispatch<super>::dispatch(this, s);
        }
    }
};

//-----------------------------------------------------------------------------
inline Visitor::~Visitor() {}

然后用于创建通用访问者:

class CommonBase { 
    IMPLEMENT_VISITOR_WITH_SUPERCLASS(void)
    virtual ~CommonBase() = 0;
};
class A : public CommonBase {
    IMPLEMENT_VISITOR_WITH_SUPERCLASS(CommonBase)
};
class B : public CommonBase {
    IMPLEMENT_VISITOR_WITH_SUPERCLASS(CommonBase)
};

class MyVisitor
    : public Visitor
    , public VTarget<CommonBase>
    , public VTarget<A>
    , public VTarget<B>
{
public:
    virtual void dispatch(CommonBase& obj);
    virtual void dispatch(A& obj);
    virtual void dispatch(B& obj);
};

使用访问者最终会产生从dynamic_cast<>Visitor的{​​{1}},这是一个交叉投射。

另一种可以实现的方法是让VTarget<T>成为Visitor的虚拟基础 - VTarget<T>然后不再需要直接从Visitor继承。 访问者::访问代码中的MyVisitor将导致虚拟基础dynamic_cast<>的向下转换。

执行演员表时,一种方法比另一种方法更快吗?或者你只是因为拥有虚拟基地而受到规模惩罚?

1 个答案:

答案 0 :(得分:1)

嗯,看起来交叉投射方法比虚拟基础方法更快。

访问需要1次回退到超类,超过1亿次迭代,交叉投射方法需要30.2747秒,虚拟基本方法需要41.3999 - 大约慢37%。

没有回退到超类的重载,交叉投射是10.733秒,虚拟基础是19.9982(慢86%)。

我更想知道dynamic_cast如何在任何一种模式下运行,真的。