惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Project Zero
Project Zero
阮一峰的网络日志
阮一峰的网络日志
博客园 - 【当耐特】
大猫的无限游戏
大猫的无限游戏
The Register - Security
The Register - Security
C
Check Point Blog
Attack and Defense Labs
Attack and Defense Labs
L
LangChain Blog
Simon Willison's Weblog
Simon Willison's Weblog
S
Schneier on Security
Recorded Future
Recorded Future
GbyAI
GbyAI
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Y
Y Combinator Blog
量子位
A
About on SuperTechFans
I
Intezer
T
Threat Research - Cisco Blogs
MongoDB | Blog
MongoDB | Blog
U
Unit 42
C
CERT Recently Published Vulnerability Notes
Scott Helme
Scott Helme
Cisco Talos Blog
Cisco Talos Blog
P
Palo Alto Networks Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Spread Privacy
Spread Privacy
M
MIT News - Artificial intelligence
雷峰网
雷峰网
博客园 - 聂微东
NISL@THU
NISL@THU
The Hacker News
The Hacker News
G
Google Developers Blog
F
Full Disclosure
博客园 - Franky
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Privacy & Cybersecurity Law Blog
博客园 - 叶小钗
酷 壳 – CoolShell
酷 壳 – CoolShell
T
The Blog of Author Tim Ferriss
Security Latest
Security Latest
T
Tenable Blog
Know Your Adversary
Know Your Adversary
Stack Overflow Blog
Stack Overflow Blog
K
Kaspersky official blog
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
C
Cybersecurity and Infrastructure Security Agency CISA
Martin Fowler
Martin Fowler
Schneier on Security
Schneier on Security

核桃的炼金工坊

2023 韩国游记 C++23: Flat Containers Deducing This Stateful Metaprogramming 推し、燃ゆ Customization Point Object 2020 总结 搞了个 C++ 构建系统 软件设计哲学(NOTE) Paxos Note 关于 cpp 可见性的黑魔法后门 一个关于 private member function detect 的 SFINAE 模板 User-defined conversion and Copy elision VIM and Latex Interface in C++ Compile Time Reflection in C++11 C++11内存模型 在C++17中的部分新特性 Const Reference of Pointer
Compare Between CRTP and Virtual
Hawtian Wang · 2018-10-16 · via 核桃的炼金工坊

我们平时都会使用虚函数来实现 C++ 里的运行时的多态,但是虚函数会带来很多性能上面的问题:

  1. 虚函数的调用需要额外的寻址
  2. 虚函数不能被 inline,当使用比较小的虚函数的时候会带来很严重的性能负担
  3. 需要在每个对象中维护一个额外的虚函数表

但是在有些情况下,我们就可以用一些静态的类型分发策略来带来一些性能上面的好处。

struct VirtualInterface {
  virtual void Skip(uint32_t steps) = 0;
};

struct VirtualImpl : public VirtualInterface {
  uint32_t index_;

  void Skip(uint32_t steps) override { index_ += steps; index_ %= INT_MAX; }
};

void VirtualRun(VirtualInterface* interface) {
  for (auto i = 0; i < N; i++) {
    for (auto j = 0; j < i; j++) {
      interface->Skip(j);
    }
  }
}

这里有一个很简单的例子,我们搞了一个简单的计数类来模拟这个过程。首先使用虚函数的方法去实现这个。在开了O2的情况下,运行了 3260628226 ns。

然后我们使用 CRTP 来实现:

template <typename Impl>
struct CrtpInterface {
  void Skip(uint32_t steps) { static_cast<Impl*>(this)->Skip(steps); }
};

struct CrtpImpl : public CrtpInterface<CrtpImpl> {
  void Skip(uint32_t steps) {
    index_ += steps;
    index_ %= INT_MAX;
  }

  uint32_t index_ = 0;
};

template <typename T>
void CrtpRun(CrtpInterface<T>* interface) {
  for (auto i = 0; i < N; i++) {
    for (auto j = 0; j < i; j++) {
      interface->Skip(j);
    }
  }
}

同样运行我们的代码, 29934437 ns。 显然在省去了查虚函数表,并且可以inline的情况下,程序有了更好的表现。

在具体的实现方式上,参考上面的实现就可以了…