C++中模板和STL介绍详解
一、模板
1.1 模板的概念
模板是C++中的一种特殊的机制,可以帮助我们实现通用的重复使用的代码。相当于对代码进行了泛化处理,将一些具体类型变成参数供调用的时候注入不同的类型,大大提高了代码的复用性。
1.2 模板的语法
模板有两种类型:函数模板和类模板。函数模板定义的函数可以用于不同类型的参数,类模板定义的类也可以用于不同数据类型的参数。
- 函数模板:
函数模板的定义方式如下:
template <typename T>
T add(T x, T y) {
return x + y;
}
其中,typename
代表类型别名,可以换成class
。
<T>
中的T
是一个类型参数列表,函数的自变量中可以使用T
来表示类型参数,返回值使用T
表示。
注:模板不可以分离到.h文件以外!
调用方式:
int main()
{
int a = 1, b = 2;
cout << add(a, b) << endl; // 3
double c = 1.5, d = 2.5;
cout << add(c, d) << endl; // 4
return 0;
}
- 类模板:
类模板的定义方式如下:
template <typename T>
class Stack {
public:
void push(T);
T pop();
private:
T elements[20];
int size;
};
template <typename T>
void Stack<T>::push(T x) {
if (size == 20) {throw "overflow";}
elements[size++] = x;
}
template <typename T>
T Stack<T>::pop() {
if (size == 0) {throw "underflow";}
return elements[--size];
}
其中,<T>
中的T
是一个类型参数列表,类的成员函数中可以使用T
来表示类型参数。
调用方式:
int main()
{
Stack<int> s1;
s1.push(1);
s1.push(2);
s1.push(3);
cout << s1.pop() << endl; // 3
cout << s1.pop() << endl; // 2
cout << s1.pop() << endl; // 1
Stack<double> s2;
s2.push(1.5);
s2.push(2.5);
s2.push(3.5);
cout << s2.pop() << endl; // 3.5
cout << s2.pop() << endl; // 2.5
cout << s2.pop() << endl; // 1.5
return 0;
}
二、STL
2.1 STL的概念
STL(Standard Template Library),是C++语言中的标准模板库,包含了大量的模板类和函数,可以提供通用的程序设计解决方案,使程序员在开发应用程序时可以少写代码,减少出错的可能。它提供了序列容器、关联容器、迭代器、算法和函数对象等各种组件,是C++工业界的核心和基础。
2.2 STL的组件
常用的STL组件有:
- 容器:vector,list,deque,set,multiset,map,multimap等容器,主要负责存储和管理元素。
- 迭代器:输入迭代器,输出迭代器,前向迭代器,双向迭代器,随机访问迭代器。
- 算法:常用算法有:sort,search,foreach,find等,是对元素进行处理的代码片段。
- 函数对象:普通函数、函数指针、函数对象。是重载了括号运算符的对象,可看作函数指针。
2.3 STL之容器详解
以下以vector、list、set为例,讲解STL中常见容器的使用方式:
- vector
vector是一个基于表达式的序列容器,是数组和链表的混合体,支持随机访问等高效操作,插入和删除元素时需要移动大量数据,所以效率较低。
定义一个vector容器:
vector<int> v1;
常用函数:
v1.push_back(10); // 增加尾元素
v1.pop_back(); // 删除尾元素
v1.insert(v1.begin(), 2);// 在第一个元素前插入2
v1.erase v1.begin(); // 删除第一个元素
v1.clear(); // 删除所有元素
v1.empty(); // 容器是否为空
v1.size(); // 容器中元素的个数
- list
list是一个基于表达式的链表容器,支持在序列的任意位置高效的插入和删除操作,但是访问操作的效率不高。
定义一个list容器:
list<int> l1;
常用函数:
l1.push_back(10); // 增加尾元素
l1.pop_back(); // 删除尾元素
l1.push_front(2); // 增加头元素
l1.pop_front(); // 删除头元素
l1.insert(l1.begin(), 2);// 在第一个元素前插入2
l1.erase l1.begin(); // 删除第一个元素
l1.clear(); // 删除所有元素
l1.empty(); // 容器是否为空
l1.size(); // 容器中元素的个数
- set
set是一个基于红黑树的关联容器,元素自动排序,也可以自定义排序规则,支持查找、删除、插入等操作,但是不支持随机访问。
定义一个set容器:
set<int> s1;
常用函数:
s1.insert(10); // 增加元素
s1.erase(10); // 删除元素
s1.clear(); // 删除所有元素
s1.empty(); // 容器是否为空
s1.size(); // 容器中元素的个数
三、示例说明
3.1 示例一
- 功能:
定义一个栈模板类,能够存取任意数据类型的元素,并能进行进栈、退栈操作。使用vector作为底层存储结构,支持动态扩容。
- 代码实现:
template <typename T>
class Stack {
public:
void push(T);
T pop();
int size();
private:
vector<T> elements;
int top = 0;
};
template <typename T>
void Stack<T>::push(T x) {
elements.push_back(x);
top++;
}
template <typename T>
T Stack<T>::pop() {
if (top == 0) { throw "underflow"; }
top--;
T result = elements[top];
elements.pop_back();
return result;
}
template <typename T>
int Stack<T>::size() {
return top;
}
3.2 示例二
- 功能:
使用STL中的set容器实现一个单词计数器。
- 代码实现:
void WordCount(string str)
{
istringstream iss(str); // 将整个字符串转化为字符流
set<string> s;
while (!iss.eof()) // 以空格为分隔符将字符串分割成单词写入set中
{
string word;
iss >> word;
s.insert(word);
}
for (set<string>::iterator it = s.begin(); it != s.end(); it++) // 排序输出
{
int count = count_if(iss.begin(), iss.end(), [&](char c) {return c == *it[0]; });
cout << *it << ":" << count << endl;
}
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++中模板和STL介绍详解 - Python技术站