一、非类型模板参数

模板参数分为:

类型模板形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。

非类型模板形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。

在前面的学习中,我们已经学习类型模板参数,接下来我们一起来看一下非类型模板参数。

在我们现阶段的学习中,非类型模板参数就是指传的是常量(现阶段只能传整型int)

假设现在我想搞一个静态的栈,按照以前的逻辑,我们是不是可以搞个宏——

代码语言:javascript

AI代码解释

#define N=10
	template<class T>
	class Stack
	{
	private:
		T _a[N];
		int _top;
	};

代码语言:javascript

AI代码解释

void test1()
{
	stack<int> st;//存储10个数据
	stack<int> st1;//存储1000个数据
}

那如果我想存储1000个数据,那是不是就要N=1000,那st中就会有空间浪费

这时候,非类型模板参数就闪亮登场~~~

代码语言:javascript

AI代码解释

namespace carrot
{
	template<class T ,size_t N=10>非类型模板参数可以给缺省值
	class Stack
	{
	public:
		Stack()
			:_a(new T[n])
		{}
	private:
		T _a[N];
		int _top;
	};
	void test1()
	{
		Stack<int, 10>  st1;//存储10个数据的静态栈
		Stack<int, 1000>  st1;//存储1000个数据的静态栈

	}
}

注意:C++20才开始支持double,int* ,现在只支持整型!!!

注意:

  1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
  2. 非类型的模板参数必须在编译期就能确认结果。
1.1 array——非类型模板参数的应用

ok,接下来我们就来介绍一下array——

文档:array - C++ Reference

array是一个静态数组,它的底层使用了非类型模板参数,然后用这个非类型模板参数定义的数组。

1.1.1 常用接口

我们看到array的接口和前面我们所学容器的接口没有啥区别,唯一的区别就是:array不支持头插、尾插以及中间插入(这是因为空间已经开好了,无法进行扩容操作)

我们看到array是一个静态数组,那array和 int a[10] 有啥区别呢?array是封装的,而a不是封装的。

这里还有个一个问题:array支持的,数组a也支持啊, 那为什么要有array?

  • 我们可以更好的用这种类型(array),开空间更快,编译时给空间

代码语言:javascript

AI代码解释

	//假如现在我想在一个链表中中的每个节点中存一个数组,用array就很方便
	list<array<int, 10>> lt;
  • 传参数,数组传参是传指针,在函数的内部不能使用范围for,而array是引用传参。

如果数组想在函数中使用范围for,就要将数组的大小传进去。

除此之外,普通数组也可以使用sort,指向数组的指针是天然的迭代器!!!

总结:再去做其他容器类型,或者进行传参时,array都有普通数组达不到的优势!!!

在前面的学习中,我们了解到:数组越界是会检查的,但是这种检查是抽查,靠近临近位置可以查出来——

但是,这些问题对于array来说,简直就是小意思~

因为array是运算符重载调用,内存严格检查!!!

二、模板的定制能力:针对特定类型的特化实现
2.1 概念

所谓“特化”,其实就是特殊化处理

通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板

 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐