作者ibmibmibm (BestSteve)
看板C_and_CPP
标题Re: [问题] 为什麽CRTP+variant还是比virtual快很多
时间Fri Jan 3 07:22:21 2020
使用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快得多。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 223.136.12.213 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1578007356.A.7A4.html
※ 编辑: ibmibmibm (223.136.12.213 台湾), 01/03/2020 07:28:04
1F:推 ab4daa: 感谢详细解说 01/03 08:34