C++的模板

模板初阶
1、泛型编程
大家有没有发现啊,我们在实现一个函数的时候,形参的类型总是多种多样的,但是呢,不同的形参类型就只能对应不同的函数
举个例子:
我们实现swap这个函数,相比大家都比较熟悉了。

void swap(int& a,int& b)
{}

void swap(double& a,double& b)
{}

对于double和int我们就得实现两个swap函数,如果有更多的形参类型,就意味着我们要实现更多的swap函数.而这些swap函数的区别也仅仅在于形参参数的不同,实现方法都是一样的。
因此C++提出了C语言所不具有的 模板这个概念

那么模板究竟是什么呢?让我们来一探究竟吧
一、函数模板

我们先记住这个语法

template <typename T>
template 是一个关键字,就是模板的意思,T是模板参数————类似于函数参数。名字不固定,可以是T,可以是K等等。
而模板参数可以有一个,也可以有多个。多个模板参数就用逗号分隔开。
template <typename T1,typename T2>typename 是类型名 也可以用class代替

让我们来动手体验一下.

namespace spj
{
	template <class T>
	void swap(T& a, T& b)
	{
		T temp = a;
		a = b;
		b = temp;
	}
}

int main()
{
	int a = 10;
	int b = 20;
	spj::swap(a, b);
	cout << a << " " << b << endl;
	double c = 1.1;
	double d = 2.2;
	spj::swap(c, d);
	cout << c << " " << d << endl;
	return 0;
}

在这里插入图片描述
有没有发现我们通过一个swap函数达到了 既能交换int类型的数据,又能交换double类型的数据,其实不只是这两种类型,其他类型也是使用的。

那么函数模板实现的原理是什么呢?
我们可以简单理解为 在传参的时候, T对传进来的参数进行了自动识别。
举个例子:
我们使用int类型传参,那么T就能够识别到int,然后将自己转换为int。

注意事项:
1、进行传参的时候,传参类型应当相同,否则编译不过.****(针对只有一个模板参数)
例:

template <class T>
void swap(T& a, T& b)
swap(1, 2.1);报错的原因是因为推演实例化错误
T不知道该推演为int 还是double类型。
修改方法可以是:
swap((double)1, 2.1)
也可以是:swap(1, (int)2.1)。
也就是转换为同一个类型就可以了。
还有一种方法是显示实例化,也就是直接告诉模板参数我传的是什么
swap<int>(1,2.1)

在这里插入图片描述
2、如果要使用不同类型的参数进行传参

template <typename T1,typename T2>
T1?T2? Add(T1& a,T2& b)
{
	return a + b;
}
如果涉及到返回值的话,该使用T1还是T2呢?还是都可以呢?
我们拿T1进行举例
template <typename T1,typename T2>
T1 Add(T1& a,T2& b)
{
	return a + b;
}

Add(10,20.1);
答案是 30.返回值类型是T1,在这里T1识别到的是int类型.因此会返回int类型。
在返回的时候进行强转。
Add(10.1,20);
答案是30.1.
因此 返回值的类型 是根据 模板参数所推理出来的类型。

同理:
对于刚刚实现的swap函数有异曲同工之处。

template <typename T1,typename T2>
void swap(T1& a,T2& b)
{
	T1 temp = a; //这里使用T1 还是T2呢?
	a = b;
	b = temp;
}
答案是,使用T1或T2 会得到不同的结果。
我们来画图解释一下

在这里插入图片描述

同理 如果temp的类型是T2,用同样的方法进行推演。

二、类模板

与函数模板相似,在类前 加入关键字 template
template <typename T>
class Stack
{
public:
	Stack() :_a(nullptr), _top(0), _capacity(0)
	{
		if (_capacity == 0)
		{
			_a = new T[4];
			_capacity = 4;
		}
	}
private:
	T* _a;
	int _top;
	int _capacity;
};

为什么要有类模板呢?
举个例子:如果我们要建一个char类型和int类型是堆.
我们就要实现两个类

class
{
private:
	int* _a;
	int capacity;
	int top;
};

class
{
private:
	char* _a;
	int capacity;
	int top;
};

如果我们使用类模板的话,我们就可以避免这样的情况发生。这也就是跟函数模板相同的原因,我们采用了泛型编程的思想。
但使用方法与函数模板上有区别。
我们在实例化对象的时候,需要将模板参数给实例化
例:
stack s1;这样是不行的。因为模板参数是推理不了参数类型的。
正确使用:
stack<int> s1. 需要将类型进行实例化。

在后续接触到STL的时候,类模板会经常使用到.后面再继续更新

### 页面调度轮转算法(Round Robin Algorithm) #### 定义与原理 轮转调度算法是一种常见的进程调度方法,在页面调度中同样适用。此算法的核心在于将固定长度的间片分配给各个任务,确保每个任务都能获得一定的处理机间[^4]。 当一个任务被加载到内存并开始运行,它会得到预先设定好的间片用于执行。如果在这个间段内未能完成,则会被暂停并将剩余部分重新加入就绪队列末端继续等待下一次调度机会。这种机制可以有效防止某些长间运行的任务独占CPU资源而造成其他短小任务长期得不到响应的情况发生[^5]。 #### 实现方式 为了实现上述逻辑,通常需要遵循以下几个方面: - **初始化阶段**:创建一个用来保存待处理任务列表的数据结构——通常是双向链表或者环形缓冲区形式的队列; - **设置合理的间片大小**:这取决于具体应用场景以及系统负载情况等因素综合考量的结果; - **核心循环体设计**: - 从队首取当前要被执行的任务; - 启动计器监控实际消耗了多少个单位间内该作业占用处理器工作; - 如果超了预定限额则强制中断其活动状态,并将其余下的指令序列送回原处排队等候下次调用; 以下是Python语言描述的一个简化版伪代码示例: ```python import time class Task: def __init__(self, name, burst_time): self.name = name self.burst_time = burst_time def round_robin(tasks, quantum): queue = tasks.copy() while queue: task = queue.pop(0) if task.burst_time > quantum: print(f"Executing {task.name} for {quantum} units.") task.burst_time -= quantum queue.append(task) # Put back to the end of the queue. yield f"{task.name}: Remaining Time={task.burst_time}" else: print(f"Executing and completing {task.name}.") yield f"{task.name}: Completed." ``` 这段程序模拟了一个简单的RR调度过程,其中`tasks`参数是一个由多个Task对象组成的列表,代表即将参与竞争计算资源的一系列候选者;`quantum`则是指定了单次允许的最大连续运作周期数。每当有一个新成员加入进来之后都会自动排在最后面依次轮流接受服务直到全部结束为止. #### 性能特点分析 对于轮转算法而言,最重要的两个影响因素分别是平均周转间和上下文切换开销。较小的间片有助于提高系统的交互性和多道程序度,但也增加了额外管理成本因为频繁地改变正在工作的线程会导致更多的寄存器保存/恢复动作。反之较大的值虽然减少了这类损耗却可能引发饥饿现象使得一些轻量级的小型事务迟迟无法真正意义上启动起来.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值