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

推荐订阅源

Project Zero
Project Zero
Martin Fowler
Martin Fowler
人人都是产品经理
人人都是产品经理
C
Check Point Blog
S
SegmentFault 最新的问题
腾讯CDC
IT之家
IT之家
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
博客园 - Franky
V
Visual Studio Blog
The Register - Security
The Register - Security
GbyAI
GbyAI
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
U
Unit 42
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
云风的 BLOG
云风的 BLOG
博客园 - 三生石上(FineUI控件)
Schneier on Security
Schneier on Security
N
News and Events Feed by Topic
T
Troy Hunt's Blog
小众软件
小众软件
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
TaoSecurity Blog
TaoSecurity Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
C
CERT Recently Published Vulnerability Notes
aimingoo的专栏
aimingoo的专栏
T
The Exploit Database - CXSecurity.com
Know Your Adversary
Know Your Adversary
G
GRAHAM CLULEY
T
Tenable Blog
P
Palo Alto Networks Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
S
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
H
Help Net Security
WordPress大学
WordPress大学
The Cloudflare Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
MongoDB | Blog
MongoDB | Blog
Forbes - Security
Forbes - Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
W
WeLiveSecurity
I
InfoQ
P
Privacy International News Feed

核桃的炼金工坊

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的情况下,程序有了更好的表现。

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