Effective C++ 条款44
2016-01-07 13:11
218 查看
本节条款的标题是:将与參数无关的代码抽离templates
学习本节条款首先须要明确一件事情,那就是模板实例化的过程会不会反复?
我们来举个样例:
我们看以上简单的代码。每一个人都知道模板被调用了两次,是的,这显而易见。但是模板也被实例化了两次吗?其实,模板仅仅实例化了一次。
我们再举个样例:
这个时候每一个人都知道模板被调用了两次。模板也被实例化了两次吗?其实,模板确实实例化了两次。
比較以上两个样例。大家明确了什么?那就是,模板函数的实例化次数和调用次数没有直接关系,而是和调用类型的种类有关。同种类型假设已经调用,模板函数会反复利用上次的实例化样例。而不会又一次分配内存实例化。假设,大家明确这一点本节条款就能理解了。
我们利用template就是为了让代码编写更简短。利用内存更小。但是,普通情况下非常多程序猿仅仅能做到第一步,而不能充分在内存中发挥代码的复用性。
例如以下书上样例:
上面的代码会在运行的过程中,详细化两份invert()函数。这两份函数差点儿全然同样,所以对于内存来说是种浪费。假设想要弥补这样的缺点,我们能够用下面对照样例:
当我们再次调用以上语句时,SquareMatrixBase类的实例在内存中仅仅生成一次。由于每次调用都是double 型的SquareMatrixBase。
然后矩阵数据是用指针訪问,同一种数据不会被拷贝多份,这样也降低了内存利用。
总之。下面三条非常重要:
1. Template生成多个classes与多个函数。所以不论什么template代码都不该与某个造成膨胀的template參数产生相依关系。
2. 因非类型模板參数而造成的代码膨胀,往往能够消除,做法是以函数參数或者class成员变量替换template參数。
3. 因类型而造成的代码膨胀,也能够降低,做法是让带有全然同样二进制表述的具现类型共享实现码。
学习本节条款首先须要明确一件事情,那就是模板实例化的过程会不会反复?
我们来举个样例:
#include<iostream> using namespace std; template <typename T> T Try(T m) { return m; } int main() { Try(10); Try(1); }
我们看以上简单的代码。每一个人都知道模板被调用了两次,是的,这显而易见。但是模板也被实例化了两次吗?其实,模板仅仅实例化了一次。
我们再举个样例:
#include<iostream> using namespace std; template <typename T> T Try(T m) { return m; } int main() { Try(10); Try(1.01);//注意!此时是一个double型 }
这个时候每一个人都知道模板被调用了两次。模板也被实例化了两次吗?其实,模板确实实例化了两次。
比較以上两个样例。大家明确了什么?那就是,模板函数的实例化次数和调用次数没有直接关系,而是和调用类型的种类有关。同种类型假设已经调用,模板函数会反复利用上次的实例化样例。而不会又一次分配内存实例化。假设,大家明确这一点本节条款就能理解了。
我们利用template就是为了让代码编写更简短。利用内存更小。但是,普通情况下非常多程序猿仅仅能做到第一步,而不能充分在内存中发挥代码的复用性。
例如以下书上样例:
template<typename T, std::size_t n>//T为数据类型,n为矩阵大小 class SquareMatrix{ public: …… void invert();//求逆运算 }; SquareMatrix<double,5> sm1; sm1.invert();//调用SquareMatrix<double,5>::invert SquareMatrix<double,10> sm2; sm2.invert();//调用SquareMatrix<double,10>::invert
上面的代码会在运行的过程中,详细化两份invert()函数。这两份函数差点儿全然同样,所以对于内存来说是种浪费。假设想要弥补这样的缺点,我们能够用下面对照样例:
template<typename T> class SquareMatrixBase { public: SquareMatrixBase(T* p) : DataPointer(p){} void Invert(size_t n){} private: T* DataPointer; }; template <typename T, size_t n> class SquareMatrix: private SquareMatrixBase<T> { public: SquareMatrix() : SquareMatrixBase(Data) {} void Invert() { SquareMatrixBase::Invert(n); } private: T Data[n * n]; }; SquareMatrix<double,5> sm1; sm1.invert(); SquareMatrix<double,10> sm2; sm2.invert();
当我们再次调用以上语句时,SquareMatrixBase类的实例在内存中仅仅生成一次。由于每次调用都是double 型的SquareMatrixBase。
然后矩阵数据是用指针訪问,同一种数据不会被拷贝多份,这样也降低了内存利用。
总之。下面三条非常重要:
1. Template生成多个classes与多个函数。所以不论什么template代码都不该与某个造成膨胀的template參数产生相依关系。
2. 因非类型模板參数而造成的代码膨胀,往往能够消除,做法是以函数參数或者class成员变量替换template參数。
3. 因类型而造成的代码膨胀,也能够降低,做法是让带有全然同样二进制表述的具现类型共享实现码。
相关文章推荐
- C++小题(十二)
- 【C++】:用sort对string类型进行排序
- 设计模式学习笔记c++版——单例模式
- POJ 1006_Biorhythms
- Sicily 1530. The Seven Percent Solution
- C语言设计ATM存取款界面
- C语言常用数学函数
- C++builder 图像字符流的存储和加载
- 【c/c++】STL标准入门汇总
- C++11多线程(十八):线程池
- C++操作Word学习笔记
- vc++中压缩文件--ZIP Util
- C++ 的一些经验!
- 关于python3调用C/C++的方法(ctypes)
- 【c/c++】类模板
- txt文本行数计算;转为二维数组;二维数组写为txt内容
- 【c/c++】函数模板和模板函数
- C语言学习之关键字第五讲
- (IOS自学)C语言基础学习(一)
- 二维码识别:Halcon与C++中多字节环境下的字节编码格式设置和转换