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

推荐订阅源

K
Kaspersky official blog
云风的 BLOG
云风的 BLOG
IT之家
IT之家
T
The Blog of Author Tim Ferriss
C
Check Point Blog
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
G
Google Developers Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
F
Fortinet All Blogs
D
DataBreaches.Net
The Register - Security
The Register - Security
L
LINUX DO - 最新话题
W
WeLiveSecurity
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V2EX - 技术
V2EX - 技术
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
小众软件
小众软件
F
Full Disclosure
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
I
InfoQ
S
Secure Thoughts
TaoSecurity Blog
TaoSecurity Blog
MyScale Blog
MyScale Blog
AI
AI
Recent Announcements
Recent Announcements
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
CXSECURITY Database RSS Feed - CXSecurity.com
V
Vulnerabilities – Threatpost
NISL@THU
NISL@THU
SecWiki News
SecWiki News
Cisco Talos Blog
Cisco Talos Blog
H
Heimdal Security Blog
Y
Y Combinator Blog
N
News | PayPal Newsroom
P
Privacy International News Feed
美团技术团队
Attack and Defense Labs
Attack and Defense Labs
D
Docker
PCI Perspectives
PCI Perspectives
Webroot Blog
Webroot Blog
A
About on SuperTechFans
A
Arctic Wolf
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
MongoDB | Blog
MongoDB | Blog
T
Threat Research - Cisco Blogs

核桃的炼金工坊

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

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