为什么虚函数调用比dynamic_cast快? [英] Why virtual function call is faster than dynamic_cast?

查看:146
本文介绍了为什么虚函数调用比dynamic_cast快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个简单的例子,它估计调用虚函数的平均时间,使用基类接口和dynamic_cast和非虚函数的调用。
这是它:

I wrote a simple example, which estimates average time of calling virtual function, using base class interface and dynamic_cast and call of non-virtual function. Here is it:

#include <iostream>
#include <numeric>
#include <list>
#include <time.h>

#define CALL_COUNTER (3000)

__forceinline int someFunction()
{
  return 5;
}

struct Base
{
  virtual int virtualCall() = 0;
  virtual ~Base(){};
};

struct Derived : public Base
{
  Derived(){};
  virtual ~Derived(){};
  virtual int virtualCall(){ return someFunction(); };
  int notVirtualCall(){ return someFunction(); };
};


struct Derived2 : public Base
{
  Derived2(){};
  virtual ~Derived2(){};
  virtual int virtualCall(){ return someFunction(); };
  int notVirtualCall(){ return someFunction(); };
};

typedef std::list<double> Timings;

Base* createObject(int i)
{
  if(i % 2 > 0)
    return new Derived(); 
  else 
    return new Derived2(); 
}

void callDynamiccast(Timings& stat)
{
  for(unsigned i = 0; i < CALL_COUNTER; ++i)
  {
    Base* ptr = createObject(i);

    clock_t startTime = clock();

    for(int j = 0; j < CALL_COUNTER; ++j)
    {
      Derived* x = (dynamic_cast<Derived*>(ptr));
      if(x) x->notVirtualCall();
    }

    clock_t endTime = clock();
    double callTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;
    stat.push_back(callTime);

    delete ptr;
  }
}

void callVirtual(Timings& stat)
{
  for(unsigned i = 0; i < CALL_COUNTER; ++i)
  {
    Base* ptr = createObject(i);

    clock_t startTime = clock();

    for(int j = 0; j < CALL_COUNTER; ++j)
      ptr->virtualCall();


    clock_t endTime = clock();
    double callTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;
    stat.push_back(callTime);

     delete ptr;
  }
}

int main()
{
  double averageTime = 0;
  Timings timings;


  timings.clear();
  callDynamiccast(timings);
  averageTime = (double) std::accumulate<Timings::iterator, double>(timings.begin(), timings.end(), 0);
  averageTime /= timings.size();
  std::cout << "time for callDynamiccast: " << averageTime << std::endl;

  timings.clear();
  callVirtual(timings);
  averageTime = (double) std::accumulate<Timings::iterator, double>(timings.begin(), timings.end(), 0);
  averageTime /= timings.size();
  std::cout << "time for callVirtual: " << averageTime << std::endl;

  return 0;
}

看起来callDynamiccast几乎需要两倍。

It looks like callDynamiccast takes almost two times more.

callDynamiccast的时间:0.000240333

callVirtual:0.0001401

任何想法为什么会这样?

Any ideas why does it?

是在现在的separete函数,所以compler不知道它真正的类型。几乎相同的结果。

EDITED: object creation is made in separete function now, so the compler does not know it real type. Almost the same result.

EDITED2:创建两种不同类型的派生对象。

EDITED2: create two different types of a derived objects.

推荐答案

虚函数调用类似于函数指针,或者如果编译器知道类型,静态调度。这是恒定时间。

The virtual function call is similar to a function pointer, or if the compiler knows the type, static dispatch. This is constant time.

dynamic_cast 是完全不同的 - 它使用一个实现定义的方法来确定类型。它不是恒定的时间,可以遍历类层次结构(也考虑mutliple继承)并执行几次查找。实现可以使用字符串比较。因此,复杂性在两个维度上更高。实时系统通常避免/阻止 dynamic_cast

dynamic_cast is quite different -- it uses an implementation defined means to determine a type. It is not constant time, may traverse the class hierarchy (also consider mutliple inheritance) and perform several lookups. An implementation may use string comparisons. Therefore, the complexity is higher in two dimensions. Real time systems often avoid/discourage dynamic_cast for these reasons.

有更多详细信息

More details are available in this document.

这篇关于为什么虚函数调用比dynamic_cast快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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