#include <iostream>
#include <map>
#include <ctime>
struct Base { virtual void foo() {} };
struct A : Base { void foo() {} };
struct B : Base { void foo() {} };
struct C : Base { void foo() {} };
A* protoA = new A; B* protoB = new B; C* protoC = new C;
enum Tag {a, b, c};
std::map<Tag, Base*> protoMap = { {a, protoA}, {b, protoB}, {c, protoC} };
void goo(Base* base) {base->foo();}
void hoo(Tag tag) {protoMap[tag]->foo();}
struct Timer {
const std::clock_t begin;
Timer() : begin (std::clock()) {}
~Timer() {
const std::clock_t end = std::clock();
std::cout << double (end - begin) / CLOCKS_PER_SEC << " seconds." << std::endl;
};
};
int main() {
const long N = 10000000;
{
Timer timer;
for (int i = 0; i < N; i++)
goo(new C); // using vtable
} // 0.445 seconds.
{
Timer timer;
for (int i = 0; i < N; i++)
hoo(c); // using map
} // 0.605 seconds.
std::cin.get();
}
但是我的测试只使用了三个派生类,而且我不知道如何定义数千个派生类来正确地进行基准测试。有没有人知道答案,所以我不必考虑如何运行更好的测试?
我处于可以轻松使用地图的情况,但是尝试使用vtable查找来提高性能需要重新设计我已经拥有的很多东西(向类中添加新的数据成员) ,定义一个新的构造函数,实现一个访问者模式等...)。
答案 0 :(得分:0)
毫无疑问,最快的方法是vtable。
实验:
您必须在类似条件下运行基准测试。为vtable基准测试的每次调用分配一个新元素是不合理的,但是不要在map方法中分配任何东西。
我使用vtable方法运行测试,使用指向已分配元素的指针。我得到16毫秒的vtable和78毫秒的地图方法。
如果你想进一步比较第1000个衍生物,你必须使用递归模板。
结果说明:
vtable查找通常使用对象的fixed offset in the vtable,而不是搜索。所以即使有1000个推导,你也会在O(1)中有一个恒定的反应时间。
地图需要对密钥执行昂贵的搜索操作,即O(log(n))。
补充说明:
您建议的地图实现在reallife中不起作用,因为您总是调用ONE SINGLE预定对象的成员函数:您存储在地图中的对象。虚拟功能将适用于该系列的任何对象。