C++ STL笔记
侯捷的视频课程的一些笔记
容器
线性容器
容器 | 结构 |
---|---|
vector | 连续数组 |
list | 循环双向链表 |
forward_list | 单向链表 |
deque | 分段连续结构 |
stack | deque,为容器的适配器(adapter) |
queue | deque,为容器的适配器(adapter) |
关联性容器
容器 | 结构 |
---|---|
set/multiset | 红黑树 |
map/multimap | 红黑树 |
unordered_multiset | 哈希表+链表 |
unordered_multiset | 哈希表+链表 |
分配器
不建议主动使用,只建议使用默认的
分配器 | |
---|---|
allocator | 默认分配器 |
operator new
分配器使用
operator new
和operator delete
管理内存,其底层就是malloc和free
OOP(Object-Oriented Programming)和GP(Generic Programing)
OOP将数据结构和算法放在一起
GP将数据结构和算法分开,两者使用iterator沟通
GP中算法使用iterator确定操作范围,并通过iterator获取容器中元素
泛化, 全特化,偏特化
特化应该是隐式实例化,显式实例化和显式具体化
迭代器iterator
迭代器设计原则
算法使用过程中迭代器需要提供的五个属性
iterator_categotry | 分类 |
distance | 距离 |
value_type | 类型 |
reference | 引用类型 |
pointer_type | 指针类型 |
template<class T>
struct _List_iterator {
typedef std::bidirectional_iterator_tag
iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef ptrdiff_t difference_type;
...
}
迭代器种类
使用结构体表示
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
STL使用模板加特化的方式针对不同的迭代器实现不同的动作
名称 | 含义 | 对应容器 |
---|---|---|
input_iterator_tag | ||
output_iterator_tag | 可写(修改)不可读 | |
forward_iterator_tag | 单向迭代,只能++而不能– | forward_list |
bidirectional_iterator_tag | 双向迭代,可以++也可以– | list |
random_access_iterator_tag | 随机访问 | vector, array, deque |
traits
iterator traits 用于区分class iterator和non-class iterator
使用特化的方式设定non-class iterator的属性
template<class I>
struct iterator_traits {
typedef typename I::value_type value_type;
}
/**
* 针对指针类型
**/
template<class T>
struct iterator_traits<T*> {
typedef typename T value_type;
...
}
template<class T>
struct iterator_traits<const T*> {
typedef typename T value_type;
...
}
除此之外,还有针对int,char,double等基本类型的traits
算法
算法结构
STL中算法和容器分开,使用迭代器进行关联
算法所有的信息智能从迭代器中获取
template<typename Iterator>
Algorithm(Iterator iter1, Iterator iter2) {
...
}
template<typename Iterator, typename Cmp>
Algorithm(Iterator iter1, Iterator iter2, Cmp cmp) {
...
}
Iterator为迭代器,Cmp为比较函数(仿函数),表示如何对两个迭代器指向的对象进行比较,通常为比较大小
仿函数functor
仿函数为算法服务,作为参数传递给算法
functor种类
算术类
进行基本算数计算
template<class T>
struct plus : public binary_function<T, T, T> {
T operator()(const T& x, const T&y) const {
return x + y;
}
}
...
逻辑运算类
进行逻辑运算
template<class T>
struct logical_and : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x && y;
}
}
...
相对关系类
将两者进行比较,大于小于或等于等
template<class T>
struct equal_to : public binary_function<T, T, bool> {
bool operator()(const T& x, const T&y) const {
return x == y;
}
}
...
functor条件
functor需要继承指定的结构体
// 包含一个参数
template<class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
}
// 包含两个参数
template<class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
}
适配器adapter
用于将STL的其他组件进行改造,使其适配需要的功能
容器适配器
种类 | 默认顺序容器 | 可用顺序容器 | 说明 |
---|---|---|---|
stack | deque | vector,list,deque | 基础容器必须提供empty() , size() , back() , push_back() , pop_back() 运算 |
queue | deque | list,deque | 基础容器必须提供empty() , size() , front() , back() , push_back() , pop_front() 运算 |
priority_queue | vector | vector,deque | 基础容器必须提供随机访问功能 |
在定义容器适配器时,模板参数的第二个参数可以指定所使用发的容器类型是哪个
函数适配器
用于对函数进行包装,可以实现类似于柯里化等操作
使用函数适配器,仿函数得符合STL仿函数的要求,即继承那两个结构体中的一个,若没有继承,则函数适配器会无法匹配仿函数拥有变量类型
bind2nd(已过时)
绑定仿函数的第二个参数(
second_argument_type
,binary_function
类型仿函数中含有该类型)为指定值
// 是否小于40
bind2nd(less<int>(), 40);
本来
less<int>()
需要传入两个参数,而使用bind2md
后将其第二个参数变为40,将该函数变为了只需要一个传入参数的函数
not1
对仿函数结果取反
是否不小于40
not1(bind2nd(less<int>(), 40));
bind
bind可以绑定的对象: 函数,函数对象(仿函数),成员函数,成员变量
绑定成员函数和成员变量时bind第一个参数必须是对应的仿函数对象
使用bind时参数按照(函数,参数1,参数2,…)的顺序,如果需要跳过,可以使用
std::placeholder
// 相当于bind2nd(less<int>, 40);
bind(less<int>(), std::placeholder::_1, 40);
对于应用类型和右值引用类型,可以使用
std::ref()
和std::move()
// 传递的为myClass的引用类型
bind(MyFunctor<MyClass>(), ref(myClass));