1. 如 size_t,int,char等。一般使用的是 size_t。

代码语言:javascript

AI代码解释

//#define N 10

template<class T, size_t N>
class Stack
{
private:
	T _a[N];//vector的内存是在堆上申请,它是动态的,如果我们需要一个静态栈的话
	size_t top;
	size_t capacity;
};

int main()
{
	Stack<int, 10> st1;
	Stack<int, 1000> st2;
	return 0;
}
  1. 如果我们使用c语言里的宏定义来控制一个静态栈的大小,那么每一个栈的大小都是固定的,为10个 T 类型所占字节;但如果我们使用非类型模板参数,我们就可以在创建栈的时候主动为它赋予一个适合的大小。
  2. 栈所占内存相比堆是非常少的,只有 1-8MB左右,而堆通常为GB级别,所以在创建静态栈等里面的一些静态数组的时候,内存不要申请过大,否则会发生栈溢出的现象。

在这里插入图片描述

在这里插入图片描述

1.2 array
  1. 相比于vector这种根据需要申请内存,只能访问已初始化的位置;静态数组则是先申请好内存,它能够访问范围内的所有位置。
  2. array是一个封装了固定大小数组容器,使用方法跟上面的自定义栈差不多。
  3. 使用array需要包头文件array。
  4. 不会初始化数据,数据还是随机值。

代码语言:javascript

AI代码解释

array<int, 10> a1;
int a2[10];
  1. 上面两者有什么不同?都不会初始化数据,都是申请一个10个int类型大小的静态数组。不同之处在于:array有严格的数组越界检查,而下面的越界检查是一种抽查(抽查相邻位置),而且只查写而不查读。

代码语言:javascript

AI代码解释

a1.fill(1);//可以使用fill进行初始化

二、模板的特化

模板的特化是在已有模板的基础之上另外进行改造,我们把这个基础模板叫做主模板,这个根据情况改造之后的模板就是特化模板

  1. 主模板它适用于大多数类型,而特化模板只适用于特定类型,使用特化模板的就不会使用主模板,特化模板的优先级更高
  2. 可以把主模板看作一个咖啡配方,这个咖啡配方适合大多数人;然后特化模板就是根据一些人的口味对咖啡配方进行微调,让这个咖啡的口味更适合这类人。而这类人有了更爱喝的咖啡之后自然就不会想去喝原来的咖啡了。
2.1 函数模板特化
  1. 函数模板是只有全特化,什么是全特化可以在下文进行了解。
  2. 函数模板特化格式:

代码语言:javascript

AI代码解释

template<>//表明这是一个特化版本
返回类型 主模板函数名<特化的类型>(主模板格式+特化类型 形参)
{
	特化内容
}
  1. 看一个例子加深理解:

代码语言:javascript

AI代码解释

//主模板
template<class T>
void Less(const T& left, const T& right)
{
	cout << "Less(const T& left, const T& right)" << endl;
}

//函数模板特化
//特化模板
template<>
void Less<double*>(double* const & left, double* const & right)
{
	cout << "Less<double*>(double* const & left, double* const & right)" << endl;
}
int main()
{
	
	Less(1, 2);
	double n1 = 1.1, n2 = 2.2;
	Less(&n1, &n2);
	return 0;
}

执行结果:

在这里插入图片描述

在这里插入图片描述

  1. 对于double*类型,它调用的是特化后的模板,而不是原模板,正所谓有了更爱喝更适合的咖啡之后就不会去喝原来的咖啡了。
  2. 一个易错点:double* const & left 里的const 要在 * 的右边。这是因为 const 修饰的应该是(double*类型)引用本身,而不是指针所指向的值。否则特化不上。

  1. const 在 * 的左边,修饰指针所指向的内容,指针所指向的内容不能更改。
  2. const 在 * 的右边,修饰指针本身,指针本身不能够修改。
2.2 类模板特化
1. 全特化

全特化就是把模板里的模板参数全部给特化掉,换成具体的类型。比如上面的函数模板特化就是这样。

例子:

代码语言:javascript

AI代码解释

//主类模板
template<class T1, class T2>
class Date
{
public:
	Date()
	{
		cout << "Date<T1, T2>" << endl;
	}
private:
	T1 _d1;
	T2 _d2;
};

//特化类模板
template<>
class Date<int, char>
{
public:
	Date()
	{
		cout << "Date<int, char>" << endl;
	}
private:
	int _d1;
	char _d2;
};


int main()
{
	Date<int, int> d1;
	Date<int, char> d2;
	return 0;
}

执行结果:

在这里插入图片描述

在这里插入图片描述

  1. template<>绝对不能漏掉。
2. 偏特化

偏特化有两种,一种是模板参数只有一部分换成具体的类型,一种是不把它们换成具体类型,而是模式特化(比如添加修饰符*)。

2.1 部分参数特化(部分参数换成具体类型)

代码语言:javascript

AI代码解释

//主类模板
template<class T1, class T2>
class Data
{
public:
	Data()
	{
		cout << "Date<T1, T2>" << endl;
	}
private:
	T1 _d1;
	T2 _d2;
};

//第一类部分参数特化
//特化第二个模板参数
template<class T1>
class Data<T1, char>
{
public:
	Data()
	{
		cout << "Date<T1, char>" << endl;
	}
private:
	T1 _d1;
	char _d2;
};
//特化第一个模板参数
template<class T2>
class Data<char, T2>
{
public:
	Data()
	{
		cout << "Date<T2, char>" << endl;
	}
private:
	char _d1;
	T2 _d2;
};
  1. 特化模板声明的时候要把没有特化的模板参数放在template<>里面,像是template<class T1>与template<class T2>。
  2. 类名后面跟参数模式,特化的把特化后的具体类型写上,没有进行特化的写原来的模板参数名。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐