STL(标准模板库),从广义上分为:容器,算法,迭代器,容器和算法之间通过迭代器进行无缝连接。
在 c++ 标准种,STL被组织成以下13个头文件:
<algorithm>
<deque>
<functional>
<iterator>
<vector>
<list>
<map>
<memory>
<numeric>
<queue>
<stack>
<utility>
容器总体分为两种:
容器是可以嵌套使用的,也就是容器可以装容器。
迭代器起到指针的作用,对指针的操作基本都可以对迭代器操作。实际上,迭代器式一个类,这个类封装一个指针。
算法,通俗的解释,就是通过优先步骤,解决一个问题。
下面给出一个简单的示例,通过这个示例,我们可以很直观的看到容器、迭代器、算法之间的密不可分的关系:
#include
#include
#include
using namespace std;
void printVector(int v)
{
cout << v << " ";
}
int main()
{
//容器
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
//迭代器
vector<int>::iterator pBegin = v.begin();
vector<int>::iterator pEnd = v.end();
//算法
for_each(pBegin, pEnd, printVector);
return 0;
}
string 和 char* 可以互相转换:
//string 转 char*
string str = "itcast";
const char* cstr = str.c_str();
//char* 转 string
const char* s = "itcast";
string sstr(s);
(1)构造函数
(2)赋值
(3)取值
两者的区别:[]方式如果访问越界,直接挂了,at()方式如果访问越界,抛出异常。
(4)拼接
+”+=”(5)查找和替换
(6)比较
(7)子串
(8)插入和删除
push_back)和删除(pop_back)的效率更高。从其他位置插入删除会引起其他元素的移动,从而效率低下。begin()和end()标识指向第一个元素和最后一个元素的下一个位置,用rbegin()和rend()标识指向最后一个元素和第一个元素的上一个位置。随机访问的概念:迭代器支持加减一个数的操作,比如v.begin() + 2
(1)构造函数
(2)赋值
(3)大小
(4)取值
(5)插入和删除
c++ 11中,针对顺序容器(如vector、deque、list),新标准引入了三个新成员,emplace_front()、emplace_back()、emplace(),分别对应push_front()、push_back()、insert(),允许我们将元素放置在容器头部、容器尾部或一个指定位置之前,但emplace_front()、emplace_back()、emplace()的效率更高。
(6)用swap()缩减容量
int main()
{
vector<int> vec;
for (int i = 0; i < 1000; i++) {
vec.push_back(i);
}
cout << vec.size() << endl;//1000
cout << vec.capacity() << endl;//1066
vec.resize(10);
cout << vec.size() << endl;//10
cout << vec.capacity() << endl;//1066
vector<int> v(vec);
cout << v.size() << endl;//10
cout << v.capacity() << endl;//10
//结论:resize只影响vector的元素的数量,但不会影响vector的容量,但vector的拷贝构造函数会使容量等于元素数量
//因此可以用匿名对象 + swap来缩小容量,swap的功能是交换两个对象
vector<int>(vec).swap(vec);
cout << v.size() << endl;//10
cout << v.capacity() << endl;//10
return 0;
}
push_back(), pop_back(), push_front(), pop_front()。begin()返回一个迭代器,指向第一个元素,end()返回一个迭代器,指向最后一个元素的下一个位置,front()返回第一个元素,back()返回最后一个元素。(1)构造函数
(2)赋值
(3)大小操作
(4)插入和删除
(5)存取
push()从栈顶增加元素,通过出栈pop()从栈顶删除元素。top()访问栈顶元素。(1)构造函数
(2)插入和删除
(3)取值
push()从队尾增加元素,通过出队pop()从队头删除元素。(1)构造函数
(2)存取、插入、删除
(3)赋值
(4)大小
双向链表,每个结点由data、prev指针和next指针构成,头节点的prev指针指向null,尾节点的next指针指向null。push_back()和pop_back()从尾部添加和删除元素,通过push_front()和pop_front()从头部添加和删除元素。通过insert()从给定位置之前插入元素。(1)构造函数
(2)插入和删除
(3)大小
(4)赋值
(5)取值
(6)翻转链表
这是list中自带的reverse和sort,不是算法中的reverse和sort。算法中的只支持可随机访问的容器。
(1)构造函数
(2)赋值
(3)大小
(4)插入和删除
(5)查找
我们可以使用仿函数来定义,仿函数是一个类,在这个类中我们重载()运算符。
//仿函数
class mycompare { //用struct定义也可以
public:
bool operator()(const int& v1, const int& v2) const {
return v1 > v2;
}
};
int main()
{
set<int, mycompare> s;
s.insert(1);
s.insert(2);
s.insert(-1);
s.insert(5);
for (auto it = s.begin(); it != s.end(); it++) {
cout << *it << endl;
}
return 0;
}
first()和second()访问。构造函数创建队组,也可以通过make_pair()函数创建队组。(1)构造函数
(2)赋值
(3)大小
(4)插入和删除
(5)查找
哈希表结构存储数据。unordered_set 容器的类模板定义如下:
template < class Key, //容器中存储元素的类型
class Hash = hash<Key>, //确定元素存储位置所用的哈希函数
class Pred = equal_to<Key>, //判断各个元素是否相等所用的函数
class Alloc = allocator<Key> //指定分配器对象的类型
> class unordered_set;
可以看到,以上 4 个参数中,只有第一个参数没有默认值,这意味着如果我们想创建一个 unordered_set 容器,至少需要手动传递 1 个参数。事实上,在 99% 的实际场景中最多只需要使用前 3 个参数(各自含义如表 1 所示),最后一个参数保持默认值即可。

unordered_map 容器模板的定义如下所示:
template < class Key, //键值对中键的类型
class T, //键值对中值的类型
class Hash = hash<Key>, //容器内部存储键值对所用的哈希函数
class Pred = equal_to<Key>, //判断各个键值对键相同的规则
class Alloc = allocator< pair<const Key,T> > // 指定分配器对象的类型
> class unordered_map;
以上 5 个参数中,必须显式给前 2 个参数传值,并且除特殊情况外,最多只需要使用前 4 个参数,各自的含义和功能如表 1 所示。
