目录
-
简介
STL 是“Standard Template Library”的缩写,中文译为“标准模板库”。STL 是 C++ 标准库的一部分,不用单独安装,命名空间std。
C++ 对模板(Template)支持得很好,STL 就是借助模板把常用的数据结构及其算法都实现了一遍,并且做到了数据结构和算法的分离。
STL 是一些容器、算法和其他一些组件的集合,它位于各个 C++ 的头文件中,以源代码的形式提供。
1.1 STL的版本
STL是一个标准,只规定了STL的接口,内部实现没有要求。STL有许多实现版本:
SGI STL版本注释丰富,结构清晰,可读性较强,GNU STL是基于SGI版本开发的,所以是最流行的版本。
CLANG 中使用的是LLVM STL, mac os中用的就是LLVM STL。
1.2 STL的组成
STL六大组件
-
容器(containers) 一些封装数据结构的模板类,例如 vector 向量容器、list 列表容器等。
-
算法(algorithms)STL 提供的数据结构算法,被设计成一个个的模板函数,大部分算法都包含在头文件 <algorithm> 中,少部分位于头文件 <numeric> 中。
-
迭代器(iterators)对容器中数据的读和写,是通过迭代器完成的,它扮演着容器和算法之间的胶合剂
-
仿函数(functors)一个类将 () 运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象(又称仿函数)。
-
配接器(adapters)使一个类的接口(模板的参数)适配成用户指定的形式,从而让原本不能在一起工作的两个类工作在一起。
-
配置器(allocators)又叫内存分配器,为容器类模板提供自定义的内存申请和释放功能,内存分配器对于一般用户来说,并不常用。
内存分配
为了减小内存碎片问题,SGI STL采用了两级配置器:
-
当分配的空间大小超过128 bytes时,会使用第一级空间配置器。第一级空间配置器直接使用malloc()、realloc()、free()函数进行内存空间的分配和释放。
-
当分配的空间小于128 Bytes时,将使用第二级空间配置器。第二级空间配置器采用了内存池技术,通过空闲链表来管理内存,初始配置一大块内存,并维护对应不同内存空间大小的的16个空闲链表,它们管理的内存块大小是8、16、24、...、128 bytes,如果有内存需求,直接在空闲链表中取,如果有内存释放,则归还到空闲链表中。
常用头文件
C++标准库定义的无扩展名的头文件
<iterator>
<functional>
<vector>
<deque>
<list>
<queue>
<stack>
<set>
<map>
<algorithm>
<numeric>
<memory>
<utility>
<string>
<unordered_set>
<unordered_map>
Mac上的源码路径:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/
容器与数据结构
下图为常见数据结构,下面会结合数据结构讲解容器的实现原理。
-
-
-
序列式容器
序列式容器:以线性排列来存储某一指定类型的数据,对应于数据结构中的线性表。
2.1 数组类容器
2.1.1 vector
vector可以看做是支持模板的动态数组容器,它满足数组内存连续存储,O(1)遍历,O(n)插入删除的特性,并且可以动态扩缩容。
vector的实现
LLVM版本vector实现
template <class _Tp, class _Allocator> class __vector_base : protected __vector_base_common<true> { public: typedef _Allocator allocator_type; typedef allocator_traits<allocator_type> __alloc_traits; typedef typename __alloc_traits::size_type size_type; protected: typedef _Tp value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::difference_type difference_type; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; typedef pointer iterator; typedef const_pointer const_iterator; pointer __begin_; pointer __end_; __compressed_pair<pointer, allocator_type> __end_cap_; };
vector的遍历
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> values{1,2,3,4,5}; //1.下标遍历 for (int i = 0; i < values.size(); i++) { cout << values[i] << " "; } cout << endl; //2.迭代器遍历 for (vector<int>::iterator pos = values.begin(); pos != values.end(); ++pos) { cout << *pos << " "; } cout << endl; //3.range for (c++11) for (const auto& value : values) { cout << value << " "; } cout << endl; //4. for_each (c++11) for_each(values.begin(), values.end (), [&](int v){ cout <<v <<" ";}); cout << endl; return 0; }
vector元素删除
#include <vector> #include <iostream> #include <algorithm> using namespace std; int main() { std::vector<int> demo{ 1,3,5,4,3,2,5,2,1 }; //1.使用迭代器删除3 for(auto iter = demo.begin(); iter != demo.end();) { if(*iter = 3){ iter = demo.erase(iter); }else{ iter++; } } for (const auto& value : demo) { cout << value << " "; } cout << endl; cout << "size is :" << demo.size() << endl; cout << "capacity is :" << demo.capacity() << endl; //2.使用remove函数交换要删除元素和最后一个元素的位置 auto iter = std::remove(demo.begin(), demo.end(), 3); cout << "size is :" << demo.size() << endl; cout << "capacity is :" << demo.capacity() << endl; //输出剩余的元素 for (auto first = demo.begin(); first != iter;++first) { cout << *first << " "; } return 0; }
vector的初始化
初始化
std::vector<char>value1(5, 'c'); std::vector<char>value2(value1); int array[]={1,2,3}; std::vector<int>values(array, array+2);//values 将保存{1,2} std::vector<int>value3{1,2,3,4,5}; std::vector<int>value4(std::begin(value3),std::begin(value4)+3);//value3保存{1,2,3}
赋值
std::vector users; //预分配内存,防止频繁动态扩容造成性能损耗 //1.reserve users.reserve(1000); for (int i = 0; i < 1000; ++i) users.pus