函数模版
概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定 类型版本。
格式
template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表)
{} // 其中typename也可换成class
template <typename T>
void Swap(T& buf1, T& buf2) {
T tmp = buf1;
buf1 = buf2;
buf2 = tmp;
}
原理
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然
后产生一份专门处理double类型的代码,对于字符类型也是如此.
函数模版的实例化
用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。
template <typename T>
T Add(const T& buf1, const T& buf2)
{
return buf1 + buf2;
}
template <typename T>
T func(int n)
{
T arr = new T[n];
return arr;
}
int main()
{
// 隐式实例化,编译器自动推演类型
cout << Add(1, 2) << endl;
cout << Add((int)1.1, 2) << endl;
cout << ((double)1, 2.2) << endl;
//cout << Add(1, 2.2) << endl; // err,因为编译器推导不出T是int类型还是double类型
// 显示实例化
cout << Add<int>(1, 2.2) << endl;
cout << Add<double>(1, 2.2) << endl;
func<int>(2); // 必须显示实例化
return 0;
}
类模板
格式
template<class T1, class T2, ..., class Tn>
class 类模板名 {
// 类内成员定义
};
使用类模板写一个通用栈
template <class T>
class Stack
{
public:
Stack(int capacity = 0) :_capacity(0), _top(0), _arr(nullptr)
{
if (_capacity > 0)
{
_capacity = capacity;
_top = 0;
_arr = new T[capacity];
}
}
~Stack() { delete[]_arr; }
void Push(const T& x)
{
if (_top == _capacity)
{
// 1. 开新空间
// 2. 拷贝数据
// 3. 删除原来的空间
int newCapacity = _capacity == 0 ? 4 : 2 * _capacity;
T* tmp = new T[newCapacity];
if (_arr != nullptr)
{
memcpy(tmp, _arr, sizeof(T) * _top);
delete[]_arr;
}
_arr = tmp;
_capacity = newCapacity;
}
_arr[_top++] = x;
}
bool IsEmpty() {
return _top == 0;
}
const T& Top()
{
assert(!IsEmpty());
return _arr[_top - 1];
}
void Pop()
{
assert(!IsEmpty());
_top--;
}
private:
T* _arr;
size_t _top;
size_t _capacity;
};