Re: [问题] 为什么CRTP+variant还是比virtual快很多

楼主: ibmibmibm (BestSteve)   2020-01-03 07:22:21
使用virtual function的时候,每个class会多一个vtable储存virtual function的
pointer:
class Interface {
public:
virtual void f() = 0;
virtual ~Interface() = default;
int a;
};
class Implement: Interface {
public:
void f() override {}
int b;
};
通常的内存分布会长这样:
0 1 2 3 4 5 6 7 8
0┌───────────────┐
│ &Implement::f │
8├───────────────┤
│ &Interface::~Interface │
16├───────┬───────┤
│ a │ b │
24└───────┴───────┘
在程式执行时要呼叫f的时候就是从vtable中拿到f的function位址来呼叫的,这就代
表有一次indirect call的时间成本。
return (*vtable[0])();
使用variant储存多种物件时,会像union一样占用最大type所占用的空间+一个标示
type用的int。
template <typename Derived>
class Interface {
public:
void f() {static_cast<Derived*>(this)->f();}
int a;
};
class Implement: Interface<Implement> {
public:
void f() {}
int b;
};
std::variant<Implement> V;
而variant储存一个Implement时候的内存分布会长这样:
0 1 2 3 4 5 6 7 8
0┌───────┬───────┐
│ type_index │ a │
8├───────┼───────┘
│ b │
16└───────┘
其中type_index是代表目前内部储存的type,-1是错误值,0是type list内第一个type。
使用visitor时,产生的程式码会像这样:
switch (type_index) {
case 0:
return visitor(*reinterpret_cast<Interface*>(&storage));
default:
throw std::bad_variant_access();
}
这里执行时的成本为一或多个condition jump,与一个jump。总体所需时间略低于一个
indirection jump,而且还能受益于branch prediction,所以这里使用variant会比使用
virtual function快得多。
作者: ab4daa (nooooooooooooooooooo)   2020-01-03 08:34:00
感谢详细解说

Links booklink

Contact Us: admin [ a t ] ucptt.com