C++学习(模板)[5]

函数模板

编译器在使用模板前要经过 模板参数推演–函数模板–推演参数实例化
函数模板的定义通常以关键字template开始,后面跟着模板参数列表和函数定义。模板参数列表中可以包含类型参数、非类型参数和模板参数包等。

#include<iostream>
using namespace std;

class A 
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};

//泛型编程    模板
template<typename T>       //模板参数(模板类型)---类似函数参数(参数对象) T为类型名字(自取)
//        也可以使用  template<class T>   极少数场景会有区别
void Swap(T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
template<class T>
T* Func(int n)
{
	T* a = new T[n];
	return a;
}

template<typename T1,typename T2>
T1 Add(const T1& left, const T2& right)
{
	return left + right;
}

//参考 https://cplusplus.com/reference/
int main()
{
	/*A* p1 = new A;
	A* p2 = (A*)malloc(sizeof(A));
	if (p2 == nullptr)
	{
		perror("malloc fail");
	}
	new(p2)A(10);*/
	int i = 0, j = 1;
	double x = 1.1, y = 2.2;
	char m = 'A', n = 'B';
	Swap(i, j);
	swap(x, y);
	swap(m, n);               //std空间自带swap函数
	cout << i << j << x << y << m << n << endl;
	Add(1, 2);
	//Add(1.1, 1); //会在推演实例化报错  T类型不明确
	//解决  自转  编译器自助推演 隐式实例化
	Add((int)1.1, 1);
	Add(1.1, (double)1);
	//显式实例化
	Add<int>(1.1, 1); //指定T的类型
	Func<A>(10);  //无法自动推演 必须显式实例化

	Add(1, 1.1);   //调用第二个双T的
	Add(1.1, 1);
	return 0;
}

实际是生成了不同的实例化函数

模板和auto的区别

在C++中,模板中的T和auto都是用于类型推导的机制,但是它们有一些区别。

  1. T是模板参数,需要在模板定义时显式指定或者通过参数推导来确定具体的类型。T可以用于函数模板、类模板等的定义中,可以作为函数参数、类成员、局部变量的类型。T可以在函数体内部使用,可以进行模板特化和模板元编程等高级用法。

  2. auto是C++11引入的关键字,用于自动推导变量的类型。auto可以用于函数返回值、函数参数、局部变量的类型推导。auto只能在函数体内部使用,不能进行模板特化和模板元编程等高级用法。

  3. T可以用于多个参数的类型推导,可以推导出多个参数的类型,例如函数模板中的两个参数类型可以相同或不同。
    auto只能用于单个变量的类型推导,无法推导出多个参数的类型。

  4. T可以在函数模板中作为参数类型,可以进行模板参数的运算和类型转换等操作。
    auto只能推导出变量的具体类型,无法进行类型转换等操作。

总的来说,T是一种通用的类型参数,可以在模板定义时指定或者通过参数推导来确定具体的类型,具有更大的灵活性和扩展性;而auto是一种用于自动推导变量类型的关键字,只能在函数体内部使用,用于简化代码和提高可读性。

类模板

类模板是一种通用的类定义,可以根据不同的类型参数生成不同的类。类模板的定义使用关键字template和模板参数来指定通用的类型,然后在类内部使用这些类型参数来定义成员变量、成员函数等。

#include<iostream>
using namespace std;

//typedef int STDataType;
template<typename T>
class Stack
{
public:
	Stack(size_t capacity = 4)
		:_a(nullptr)
		, _top(0)
		, _capacity(0)
	{
		if (capacity>0)
		{
			_a = new T[capacity];
			_top = 0;
			_capacity = capacity;
		}
	}
	~Stack()
	{
		delete[] _a;
		_a = nullptr;
		_capacity = _top = 0;
	}
	void Push(const T& x);
	
	void Pop()
	{
		assert(_top > 0);
		--_top;
	}
	bool Empty()
	{
		return _top == 0;
	}
	const T& Top()
	{
		assert(_top > 0);
		return _a[_top - 1];
	}
private:
	//STDataType* _a;
	T* _a;
	size_t _top;
	size_t _capacity;
};
//类模板不支持声明和定义分离(分到.c和.h)  在一个文件中支持声明定义分离
template<class T>
void Stack<T>::Push(const T& x)
{
	
		if (_top == _capacity)
		{
			size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
			T* tmp = new T[newcapacity];
			if (_a)
			{
				memcpy(tmp, _a, sizeof(T) * _top);
				delete[] _a;
			}
			_a = tmp;
			_capacity = newCapacity;
		}
		_a[_top] = x;
		++_top;
	
}
int main()
{
	Stack<int> st1;
	Stack<char> st2;//实际是两个类
	st1.Push(1);
	st1.Push(2);
	st1.Push(3);
	while (!(st1.Empty()))
	{
		cout << st1.Top() << ' ';
		st1.Pop();
	}
	cout << endl;
	return 0;
}

模板的显示实例化

在C++中,可以使用显示实例化来显式地告诉编译器实例化一个特定的模板。显示实例化可以用于函数模板和类模板。

对于函数模板,可以使用以下语法进行显示实例化:

template <typename T>
void foo(T arg);

template void foo<int>(int arg);  // 显示实例化为int类型
template void foo<double>(double arg);  // 显示实例化为double类型

在上面的代码中,template void foo<int>(int arg);template void foo<double>(double arg);分别表示将foo函数模板实例化为int类型和double类型。

对于类模板,可以使用以下语法进行显示实例化:

template <typename T>
class Bar {
    // 类定义
};

template class Bar<int>;  // 显示实例化为int类型
template class Bar<double>;  // 显示实例化为double类型

在上面的代码中,template class Bar<int>;template class Bar<double>;分别表示将Bar类模板实例化为int类型和double类型。

显示实例化可以在编译时生成特定类型的函数或类的实例,可以用于优化编译时间和生成更小的可执行文件。但需要注意的是,显示实例化会增加编译时间和生成的代码量,因此应该谨慎使用,只在必要时进行显示实例化。

另外,C++17引入了template<>的语法,可以直接对模板进行特化,而无需提供具体的参数类型。这种特化方式也可以用于显示实例化,例如:

template <>
void foo<int>(int arg);  // 显示实例化为int类型的特化
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值