C++笔记⑤模板与STL

81 阅读4分钟

一、模板

(一)函数模板

1.定义:

函数模板名(形式参数表){
//函数体
}

2.赋默认值:P13啥意思?

(二)类模板

1.定义:

class 类模板名 {
//类定义体
};

2.实例化:

1717994154006.png

3.类模板的成员函数定义

//放在类模板的定义体中,与类的成员函数定义格式相同;或在全局区域中定义
template<类型形式参数表>
函数返回值类型 类模板名<类型名表>::成员函数名(形参表){
//函数体}
#include <iostream>
using namespace std;

//定义类模板AClass,包括两个成员函数 
template<class T, int N>
class AClass {
	private:
		T values[N];
	public:
		//成员函数的模板参数(类内定义) 
		//template<class T, int N>
		void Set(int x) {
			for(int i = 0; i < N; i++) {
				values[i] = x + i;
			}
		}
		void Show();
};
//成员函数的模板参数(类外定义) 
template<class T, int N>
void AClass<T, N>::Show() {
	for(int i = 0; i < N; i++)
		cout<<"values["<<i+1<<"]="<<values[i]<<endl;
}
int main() {
	AClass<int, 5> a1;//模板类实例化得到对象 
	a1.Set(2);
	a1.Show();
	AClass<double, 10> a2;
	a2.Set(10);
	a2.Show();
	return 0;
}
//输出
//values[1]=2//values[2]=3//values[3]=4//values[4]=5//values[5]=6//values[1]=10//values[2]=11//values[3]=12//values[4]=13//values[5]=14//values[6]=15//values[7]=16//values[8]=17//values[9]=18//values[10]=19 
  • 普通类的成员函数,也可定义为类模板
  • 类模板的成员函数,也可有额外的模板参数
class normal_ class {
	public:
		int value;
		//类内定义 
		template<typename T>
		void set(T const& v) {
			value = int(v);
		}
		template<typename T>
		T get();
};
//类外定义 
template<typename T>
T normal_class::get() {
	return T(value);
}

template<typename T0>
class A {
	public:
		T0 value;
		//类内定义 
		template<typename T1>
		void set(T1 const& v) {
			value = T0(v);
	}
		template<typename T1>
		T1 get();
};
//类外定义 
T1 A::get() {
	return T1(value);
}

4.模板参数是另一个类模板

template<typename T, template<typename TT0, typename TT1> class A>
struct Foo{
A<T, T>bar;
};

5.模板特化

  • 对函数模板,如果有多个模板参数,则特化时必须提供所有参数的特例类型,不能部分特化。template<>char* sum(char *a, char *b){}template<><char*> sum(char *a, char *b){}
  • 对于类模板,允许部分特化,即部分限制模板的通用性。template<class T1>class A<T1, int>{...}若指定所有类型,则<>内为空template<> class A<int, int>{...}

二、迭代器

1.内敛函数

  • inline int min(int a, int b){return (a>b)?a:b;}
  • 避免函数调用开销空间换时间
  • 在类定义体内定义的函数缺省为内联函数

2.变与不变

  • 不变:算法/抽象结构的接口与实现;“数据”的访问接口不变(迭代器);“数据”的可用操作(操作符重载)
  • 变:“数据”的组织形式;“数据”的类型(值域、存储、操作实现)

三、STL标准模板库Standard Template Library

(一)容器

cbb1f01be3122a7a54eea2464a8b8d5.png

1.顺序容器

  • 将元素按照严格的线性形式组织起来
  • 对元素的访问可以采用顺序方式或随机方式
  • 包括vector、list、deque

2.关联容器

  • 将元素按照非线性形式组织起来
  • 根据一组索引来快速的访问元素
  • 包括set、multiset、map、multimap

3.vector

  • 内部用动态数组来存放元素
  • 长度可变是一个类模板,元素类型任意

常用成员函数
vector()创建一个长度为0的空向量
vector(size_type n, const T &val=T())创建一个长度为n的向量,每个元素的初始值为val
size_type size()const返回当前容器中元素的个数
size_type capacity()const返回容器当前可存放元素的个数
bool empty()如果容器为空则返回true,否则返回false
void push_back(const T &x)在容器末尾添加元素x
void clear()删除容器中的全部元素
void reserve(size_type n)重新分配内容,使其可存放n个元素

#include <iostream>
#include<vector>
using namespace std;

int main() {
	int i;
	vector<int> v1;
	for(i = 0 ; i < 3; i++) 
		v1.push_back(i+1);
		v1.reserve(5);
	for(i = 0 ; i < 5; i++)
		cout<<v1[i]<<endl;
	cout<<endl;
	vector<double> v2(5, 7.8);
	for(i = 0 ; i < v2.size(); i++)
		cout<<v2[i]<<endl;
	return 0;
}

(二)迭代器

  • 是一种通用指针,可以方便对容器进行定位和操作
  • 每个容器都有自己的迭代器

vector的与迭代器相关的常用成员函数
iterator insert(iterator it, const T &x)在迭代器it所指的位置前插入元素x
iterator erase(iterator it)删除迭代器it指向的元素
iterator begin()返回指向第一个元素的迭代器
iterator end()返回指向最后一个元素后一个位置的选代器

#include <iostream>
#include<vector>
using namespace std;

int main() {
	vector<double> v1(5, 7.8);
	vector<double>::iterator it1;
	for(it1 = v1.begin(); it1 < v1.end(); it1++)
		cout<<*it1<<endl;
		
	vector<char> v2;
	v2.push_back('b');
	vector<char>::iterator it2;
	it2 = v2.begin();
	v2.insert(it2, 'a');
	it2 = v2.end();
	v2.insert(it2, 'c');
	for(it2 = v2.begin(); it2 < v2.end(); it2++)
		cout<<*it2<<endl;
	
	return 0;
}
//output:
//7.8
//7.8
//7.8
//7.8
//7.8
//a
//b
//c 

(三)算法

sort(v.begin(), v.end());