大家好,我是苏貝,本篇博客带大家了解C++的string类的遍历+vs和g++下string的结构,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
目录
1 非类型模板参数
模板参数分为类型形参与非类型形参。
类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参:用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
下图定义了一个模板类型的静态数组
可能有些人会觉得这和在构造函数里动态开辟类似,但不一样。这是在编译时就开辟了,但构造函数内的是在运行时动态开辟
注意:目前只支持整形做非类型模板参数
2 模板的特化
1. 概念
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板
来看下面的3个比较
第3个比较结果错误,因为传的参数是指针,那就是对地址进行比较,但是日期小的不一定地址也小,所以结果错误
此时,就需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化中分为函数模板特化与类模板特化。
2. 函数模板特化
函数模板的特化步骤:
- 必须要先有一个基础的函数模板
- 关键字template后面接一对空的尖括号<>
- 函数名后跟一对尖括号,尖括号中指定需要特化的类型
- 函数形参表:必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出,即给出一个重载函数,而非函数模板特化。
该种实现(重载)简单明了,代码的可读性高,容易书写,因此函数模板不建议特化。
3. 类模板特化
(A) 全特化
全特化即是将模板参数列表中所有的参数都确定化。
(B) 偏特化/半特化
偏特化/半特化:任何针对模版参数进一步进行条件限制设计的特化版本。偏特化有以下两种表现方式
- 部分特化:将模板参数类表中的一部分参数特化。
- 参数更进一步的限制:
偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本
注意:这里偏特化的class A<T1*,T2*>的T1,T2与template<class T1,class T2>的T1,T2不同。举例:上图的a2是用参数int*,char进行模板实例化的,所以template<class T1,class T2>的T1,T2分别是int,char*。在class A<T1*,T2*>的T1整体,T2整体才是int*,char*。且后续如果需要使用2个参数,就要使用*T1,*T2,不能用T1,T2
3. 模板分离编译
1 什么是分离编译
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。
2 模板的分离编译
假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:
文件a.h
文件a.cpp
文件test.cpp
这个程序编译成功
但要运行程序时却失败了,提示说链接错误,且只有size()错误,func()没错,但它们都有声明和定义,这是为什么?
(A). 出错原因
在C/C++中,一个程序要运行起来,需要经历4个阶段:预处理、编译、汇编、链接。在预处理阶段,头文件展开。
文件a.cpp
文件test.cpp
a.cpp编译时,size和func都只有声明,检查一下函数名和参数匹配,没问题就暂且过了。对a.size,知道实例化T是什么类,但是没有size函数定义,就不能实例化。
a.cpp编译时,有函数的定义,但是不知道实例化T的类型,所以有定义但无法实例化
再汇编,再链接,链接时test.cpp就需要知道size和func的函数地址,func函数有定义,知道地址,但size函数需要实例化的函数,没有,报错
(B). 解决方法
- 显示实例化(不推荐)
在size定义的文件里加显示实例化
test.cpp中,调用size的a的参数是int,就要在size定义的文件中加下图红框框的内容
如果test.cpp中,还有调用size的b的参数是double,那么还要在size定义的文件中再加
这太麻烦了,它要求只要调用size的对象的参数是之前未出现的(在上图就是除int和double之外的),那就要在size定义的文件中加显式实例化。因此我们不推荐这样写
- 将模板的声明和定义放在同一个文件中(推荐)
也就是说,模板的声明和定义可以分离,但都放在一个文件里
为什么模板的定义和声明放到同一个文件里,就不报链接错误了?
因为test.cpp预处理时,头文件展开,这里面既有size声明也有定义,我们也知道size的模板参数T的类型,就直接实例化,知道函数地址
4. 模板总结
优点:
- 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
- 增强了代码的灵活性
缺点:
- 模板会导致代码膨胀问题,也会导致编译时间变长
- 出现模板编译错误时,错误信息非常凌乱,不易定位错误
好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️