关于CRTP(Curiously Recurring Template Prattern)的使用
在阅读frameworks/rs/cpp/util/RefBase.h之LightRefBase时,我记得《C++设计新思维》里对这种用法是有过介绍的,可是今天翻箱倒柜,怎么都找不到那本奇书了。当年所谓的前卫,今天已经遍地开花,赶紧再把CRTP给复习一下。
CRTP模式主要有两种使用场景:
- 一、Meyers Counting
template <typename T> class Counting { public:Counting() { mCount++; }~Counting() { mCount--; }static int mCount; };template <typename T> int Counting<T>::mCount = 0;class CountedA : public Counting<CountedA>{}; class CountedB : public Counting<CountedB>{};
CountedA类和CountedB类都具备了引用计数功能,这是从Counting基类派生下来的,但是引用计数具体的数值是每个子类各自维护,这主要是拜mCount的static属性所赐,Counting<CountedA>和Counting<CountedB>是不同的类,也就有不同的静态成员。
不过LightRefBase显然不是这种应用场景。
- 二、用编译时绑定替代运行时绑定,避免虚表的时空性能开销。
#include "stdafx.h" #include <stdio.h>template <typename T> class Fucker { public:void doFuck() { printf("Failed :(\n"); }void Fuck() { ((T*)this)->doFuck(); } };class AFucker : public Fucker<AFucker> {};class BFucker : public Fucker<BFucker> { public:void doFuck() { printf("Shuang :)\n"); } };int main(int argc, char** argv) {Fucker<BFucker>* pFucker = new BFucker();pFucker->Fuck();return 0; }
上面,Fuck()和doFuck()共同完成了虚函数的表演,但无需承担虚表的开销。乍一看LightRefBase也不是这种设计,因为它显然没有虚函数的桥段。
1 template <class T> 2 class LightRefBase 3 { 4 public: 5 inline LightRefBase() : mCount(0) { } 6 inline void incStrong(__attribute__((unused)) const void* id) const { 7 __sync_fetch_and_add(&mCount, 1); 8 } 9 inline void decStrong(__attribute__((unused)) const void* id) const { 10 if (__sync_fetch_and_sub(&mCount, 1) == 1) { 11 delete static_cast<const T*>(this); 12 } 13 } 14 //! DEBUGGING ONLY: Get current strong ref count. 15 inline int32_t getStrongCount() const { 16 return mCount; 17 } 18 19 typedef LightRefBase<T> basetype; 20 21 protected: 22 inline ~LightRefBase() { } 23 24 private: 25 friend class ReferenceMover; 26 inline static void moveReferences(void*, void const*, size_t, 27 const ReferenceConverterBase&) { } 28 29 private: 30 mutable volatile int32_t mCount; 31 };
它唯一使用了模板参数的地方就是#11,可以断定此处就是该设计的初衷。如果用派生的方式,也可以完成这个任务:
1 class Base 2 { 3 public: 4 Base() :mCount(0) {} 5 int IncRef() { return ++mCount; } 6 int DecRef() { 7 if (--mCount <= 0) { 8 delete this; 9 } 10 return mCount; 11 } 12 virtual ~Base() {} 13 private: 14 int mCount; 15 }; 16 17 class Derived : public Base 18 {};
可这样一来就要引入虚表了——有一个析构虚函数。为什么必须要有它呢?因为Base要用于派生。《Effective C++》第14条曰:总让base class拥有virtual destructor,因为经由基类指针删除子类对象时,基类如果没有虚析构函数,结果将是未定义。于是定义虚析构函数,于是引入虚表。LightRefBase对象的开销本来只有一个int32_t那么大,引入虚表,空间开销就double啦,大大得不划算。因此采用了CRTP模式,算是场景二的变种。
转载于:https://www.cnblogs.com/palance/p/5194164.html
关于CRTP(Curiously Recurring Template Prattern)的使用相关推荐
- 奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)
The Curiously Recurring Template Pattern (CRTP) is a C++ idiom whose name was coined by James Coplie ...
- 计算机编程英文术语,计算机编程英语词汇
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 containment 包容 context 环境.上下文 control 控件 cookie (不译) copy 拷贝 CORBA 通用对象请求中介架构 ...
- 计算机编程英语用语,计算机编程英语词汇
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 containment 包容 context 环境.上下文 control 控件 cookie (不译) copy 拷贝 CORBA 通用对象请求中介架构 ...
- IT英语2-编程词汇编程英语词汇
IT英语2-编程词汇编程英语词汇 A2A integration A2A整合 abstract 抽象的 abstract base class (ABC)抽象基类 abstract class ...
- 计算机编程学英语词汇,计算机编程英语词汇大全
index 复合索引.组合索引 (for database) composite key 复合键.组合键 (for database) composition 复合.组合 41.concept 概念 ...
- 【转】软件开发常用术语
软件开发技术常用术语 A.I. 人工智能 A2A integration A2A整合 abstract 抽象的 abstract base class (ABC)抽象基类 abstract class ...
- Java基础常见英语词汇
"ctrl+F"输入关键字来查找 第一章: JDK(Java Development Kit) java开发工具包 JVM(Java Virtual Machine) java虚拟 ...
- 计算机常用英语单词对照
第一部分.计算机算法常用术语中英对照 Data Structures 基本数据结构 Dictionaries 字典 Priority Queues 堆 Graph Data Structures 图 ...
- Java英语单词(5000个)
Java基础常见英语词汇 OO: 面向对象 OOP: object-oriented programming,面向对象编程 JDK:Java development kit, java开发工具包 J ...
最新文章
- Java项目:进销存系统(java+Gui)
- AC日记——最大子段和 洛谷 P1115
- GUID和INT两种数据类型做主键的比较
- hive python脚本,Hive调用Python脚本错误
- [Apache]安装中出现的问题
- mongodb的条件查询笔记
- c#编程指南(十二) 平台调用P-INVOKE完全掌握, 结构体边界对齐和内存布局
- Android 数据库 在使用 update更新的时候,总是无法更新,还没有异常抛出!
- CloudStack 4.4学习总结之注册ISO
- Redis集群原理详解
- 使用pthread后,界面假死现象问题
- 保研面试/考研复试英语口语常见问题整理
- css实现半圆(上下左右半圆)
- “日历提醒app”程序说明文档
- 根据Magic Number(幻数)判断文件类型
- linux动态库注册函数,linux下加载动态库函数
- python写对象提供的方法_下面哪些是python读对象提供的“写”方法?
- OCR开源库Tesseract汉字识别训练
- 较好的应用计算机,电脑跑分软件哪个好用?哪个比较权威?电脑跑分软件排行榜2017年...
- 磁盘管理1(磁盘碎片、磁盘格式转换)
热门文章
- 使用sublime编译运行C程序
- 如何用python做计算_如何运用Python编写简易计算器?
- 微计算机应用 官网,按照影响因子,查找与计算机通信与技术专业相关的权威期刊...
- mysql 存储过程 互斥_mysql中的存储过程和事务隔离
- HALCON标定倾斜安装镜头
- c++ 包络谱分析代码_基于特征分析谱估计算法(Capon, MUSIC, ESPRIT)的C++实现
- 《effective java》类和对象
- 理解LSTM/RNN中的Attention机制
- 莫比乌斯函数+莫比乌斯反演
- linux bash基础