gpt4 book ai didi

c++ - 为什么虚函数调用比 dynamic_cast 快?

转载 作者:可可西里 更新时间:2023-11-01 17:08:14 27 4
gpt4 key购买 nike

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

#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 花费了将近两倍的时间。

调用动态广播的时间:0.000240333

调用虚拟时间:0.0001401

知道为什么会这样吗?

已编辑:对象创建现在是在单独的函数中进行的,因此编译器不知道它的真实类型。几乎相同的结果。

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

最佳答案

虚函数调用类似于函数指针,或者如果编译器知道类型,静态分派(dispatch)。这是常数时间。

dynamic_cast 完全不同——它使用实现定义的方式来确定类型。不是常数时间,可能遍历类层次结构(也考虑多重继承)并执行多次查找。一个实现可以使用字符串比较。因此,二维的复杂度更高。由于这些原因,实时系统经常避免/劝阻 dynamic_cast

更多详情可用in this document .

关于c++ - 为什么虚函数调用比 dynamic_cast 快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9959315/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com