三十一章 STL 容器
-
顺序容器
- vector<T, A=std::allocator
> - list<T,A>
- forward_list<T,A>
- deque<T,A>
- vector<T, A=std::allocator
-
优先选用vector,除非有其他特殊理由
-
有序关联容器,C是比较类型,A是分配器类型,用平衡二叉树(通常是红黑树)实现
- map<K,V, C=std::less
, A=std::allocator<std::pair<const K,V>>> - multimap<K,V,C,A>
- set<K,C, A=st::allocator
> - multiset<K,C,A>
- map<K,V, C=std::less
-
无序关联容器:H是哈希函数类型,E是相等性测试,用溢出链表法的哈希表实现
- unordered_map<K,V, H=std::hash
, E=std::equal_to ,A> - unordered_multimap<K,V,H,E,A>
- unordered_set<K,H,E,A>
- unordered_multiset<K,H,E,A>
- unordered_map<K,V, H=std::hash
-
容器适配器,C是容器类型
- priority_queue<T, C=std::deque
,Cmp=std::less >:T的优先队列,Cmp是优先级函数类型 - queue<T, C=std::vector
> - stack<T, C=std::vector
>
- priority_queue<T, C=std::deque
-
拟容器:具有标准容器大部分特性,但非全部
- T[N], 内置数组
- array<T,N>
- basic_string<C,Tr,A>: Tr表示字符萃取
- valarray
: 数值向量,支持向量运算,适合大量向量运算情形 - bitset
: N个二进制位集合,支持集合操作 - vector
: vector 特例化版本,紧凑保存二进制
-
对元素的要求:对象类型必须允许容器拷贝、移动以及交换元素。
-
若对象无法拷贝,替换方案是把对象的指针保存在容器中
-
关联容器要求元素能够排序,排序标准必须定义一个严格弱序
-
构造函数、析构函数、赋值操作
-
C c{}
-
C c{a} //a,分配器
-
C c(n) //关联容器不适用
-
C c(n,x)//x的n个拷贝,关联容器不适用
-
C c{elem}//用elem初始化c,如C有初始化器列表构造函数,优先使用
-
C c{c2}
-
C c{move(c2)}
-
C c{{elem},a}
-
C c{b,e}// [b,e)
-
C c{b,e,a}
-
c.~C()
-
c2=c
-
c2=move(c)
-
c={elem}
-
c.assign(n,x)//关联容器不适用
-
c.assign(b,e)
-
c.aasign({elem})
赋值操作不会拷贝或移动分配器
-
-
容器通常都很大,一般以引用或移动来传递实参和返回值
-
大小和容量
- c.size()
- c.empty()
- c.max_size() //c的最大可能元素数目
- c.capacity() //vector, string
- c.reserve(n) //vector, string, 提高性能可预测性和避免迭代器失效的方式
- c.resize(n) //增加的元素是默认值,适用于顺序容器和string
- c.reserve(n,v) //增加的元素初始化位v,顺序容器和string
- c.shrink_to_fit(). //capacity==size, vector deque string
- clear()
- 改变大小和容量时,注意迭代器可能会失效。关联容器元素的迭代器只有当元素被删除时才失效
-
迭代器
begin() ,end() ,cbegin() ,cend() ,rbegin() ,rend() ,crbegin() ,crend()
-
元素访问
- c.front() //首元素,关联容器不适用
- c.back() //尾元素,forwart_list 和关联容器不适用
- c[i] //不做范围检查,链表和关联容器不适用
- c.at(i) //若i超出范围,抛出out_of_range异常,链表和关联容器不适用
- c[k] //若未找到则插入(k,mapped_type{}),只适用于map和unordered_map
- c.at(k)//若未找到抛出out_of_range异常,只适用于map和unordered_map
-
栈操作
- c.push_back(x) //使用拷贝或移动
- c.pop_back() //删除尾元素,不返回值
- c.emplace_back(args) //用args构造一个元素添加到c的尾元素之后
-
列表操作
- q=c.insert(p,x) //x插入到p之前,使用拷贝或移动
- q=c.insert(p,n,x) //p之前插入x的n个拷贝,若c为关联容器,p不是插入位置,而是提示搜索开始位置
- q=c.insert(p,first,last) //p之前插入[first,last),不适用关联容器
- q=c.insert(p,{elem})//与2类似
- q=c.emplace(p, args) //不适用于关联容器
- q=c.erase(p)
- q=c.erase(first, last) //删除[first, last)
- c.clear()
- insert系列函数返回结果q指向插入的最后一个元素,erase的q指向删除的最后一个元素之后的位置
- forward_list 使用insert_after, 无序容器使用emplace_hint()
-
其他操作
c1==c2, c1!=c2, c1<c2, c1<=c2, c1>c2, c1>=c2 //比较元素
c1.swap(c2) //交换元素和分配器,不抛出异常
swap(c1,c2)
-
vector
- 元素紧凑存储,所有元素不存在额外内存开销,大致为sizeof(vecor
) + vec.size()*sizeof(X) - 遍历特别快,没有间接寻址开销
- 高效的随机访问
- 元素紧凑存储,所有元素不存在额外内存开销,大致为sizeof(vecor
-
list,forward_list
1. 插入,删除高效,不影响其他元素迭代器
2. 每个list元素占有更多空间,通常每个元素至少多4个字
3. 遍历慢,间接寻址
4. forward_list 看作为空链表和很短的链表的优化
-
list forward_list 共同操作
- lst.push_front(x)//插入首元素之前,使用移动或者拷贝
- lst.pop_front()//删除首元素
- lst.emplace_front(args)//将T{args}添加到首元素之前
- lst.remove(x)//删除所有等于x的元素
- lst.remove_if(f) //删除所有满足f(x)==true的元素
- lst.unique() //删除所有相邻重复元素
- lst.unique(f) //与6相同,用f判断
- lst.merge(lst2) //合并有序链表lst和lst2,用<确定序,将lst2合并入lst,lst2被情况,稳定算法
- lst.merge(lst2, f)//与8相同,用f确定序
- lst.sort()//排序,用<确定序
- lst.sort(f) //排序,用f确定序
- lst.reverse()//反转lst中的元素,不抛出异常
-
list
操作 - lst.splic(p, lst2) //将lst2插入到p之前,lst2变为空
- lst.splice(p, lst2, p2) //将p2指向的lst2的元素插入到p之前,该元素从lst2中删除
- lst.splice(p, lst2, b, e) //将[b,e)指向的元素插入p之前,这些元素从lst2删除
-
forward_list
无法访问迭代器之前的元素,emplace, insert, erase, splice都作用于迭代器之后的位置: - p2=lst.emplace_after(p, args)
- p2=lst.insert_after(p,x)
- p2=lst.insert_after(p, n, x)
- p2=lst.insert_after(p, b, e)
- p2=lst.insert_after(p, {elem})
- p2=lst.erase_after(p) //删除p之后的元素,p2指向p之后的元素或lst.end()
- p2=lst.erase_after(b,e)//删除[b,e)间的原属,p2指向e
- lst.splice_after(p, lst2)
- lst.splice_after(p, b, e)
- lst.splice_after(p, lst2, p2)
- lst.splice_after(p, lst2, b, e)
-
map<K, T, C, A>构造函数: cmp是比较器,a是分配器
- map m{cmp, a}
- map m{cmp}
- map m{}
- map m{b,e,cmp,a}
- map m{b,e,cmp}
- map m{b,e}
- map m{m2} //拷贝和移动构造函数
- map m{a}
- map m{m2, a}
- map m{ {elem}, cmp, a}
- map m{ {elem}, cmp}
- map m{ {elem} }
-
关联容器操作
- p=c.lower_bound(k) //p指向关键字>=k的第一个元素或c.end()(未找到),只适用于有序容器
- p=c.upper_bound(k) //p指向关键字>k的第一个元素或c.end()(未找到),只适用于有序容器
- pair(p1, p2)=c.equal_range(k) // p1=c.lower_bound(k), p2=c.upper_bound(k)
- pair(p,b)=c.insert(x)//x是一个value_type或能拷贝入一个value_type的某种东西(如一个双元素的tuple)。若x成功插入,则b为true;若容器中已有元素与x关键字相同,b为false;p指向关键字与x相同的(可能是新的)元素
- p2=c.insert(p, x) //x与4相同,p提示从哪里开始搜索关键字与x相同的元素;p2指向关键字与x相同的元素
- c.insert(b,e) //对[b,e)间的每个p,执行c.insert(*p)
- c.insert({args}) // 将initializer_list args中的每个元素插入容器,元素类型为pair<key_type, mapped_type>
- p=c.emplace(args)//从args构造类型为value_type的对象,插入c,p指向该对象
- p=c.emplace_hint(h, args) //与8相同,h为c中迭代器,用来指示从哪里开始搜索新元素存放位置
- r=c.key_comp()//r是关键字比较对象的一个拷贝,只适用于有序容器
- r=c.value_comp()//r是值比较对象的一个拷贝, 只适用于有序容器
- n=c.count(k) //n为关键字等于k的元素数目
-
关联容器中元素的关键字是不可变的。
-
unordered_map<K,T,H,E,A>构造函数
- unordered_map m{n, hf, eql, a}; //构造n个桶的m,哈希函数hf,相等比较函数eql,分配器为a
- unordered_map m{n, hf, eql}
- unordered_map m{n, hf}
- unordered_map m{n}
- unordered_map m{}
- unordered_map m{b, e, n, hf, eql, a}// 初始元素[b,e)
- unordered_map m{b, e, n, hf, eql}
- unordered_map m{b, e, n, hf}
- unordered_map m{b, e, n}
- unordered_map m{b, e}
- unordered_map m{ {elem}, n, hf, eql, a} //初始元素{elem}
- unordered_map m{ {elem}, n, hf, eql}
- unordered_map m{ {elem}, n, hf}
- unordered_map m{ {elem}, n}
- unordered_map m{ {elem}}
- unordered_map m{m2}
- unordered_map m{a}
- unordered_map m{m2, a}
-
哈希和相等判定函数:函数对象,lambda,特例化标准库hash和equal_to模版
-
哈希策略
- h=c.hash_function()//h为c的哈希函数
- eq=c.key_eq()//eq是c的相等性检测函数
- d=c.load_factor() //d是元素数除以桶数:double(c.size())/c.bucket_count(),不抛出异常
- d=c.max_load_factor()//最大装载因子,不抛出异常
- c.max_load_factor(d)//将c的最大装载因子设置为d,若c的装载因子已经接近其最大装载因子,c将改变哈希表大小(增加桶数)
- c.rehash(n)//令c的桶数>=n
- c.reserve(n)//留出能容纳n个表项的空间(考虑装载因子):c.rehash(ceil(n/c.max_load_factor()))
-
用异或操作组合标准哈希函数得到的哈希函数通常有很好的性能
-
70%的装载因子通常是一个好选择
-
桶相关接口
- n=c.bucket_count(). //c的桶数n,noexcept
- n=c.max_bucket_count()//一个桶中最大元素数n,noexcept
- m=c.bucket_size(n)//第n个桶中元素数m
- i=c.bucket(k) //关键字k的元素在第i个桶中
- p=c.begin(n)//p指向桶n中首元素
- p=c.end(n) //p指向桶n中尾元素之后的位置
- p=c.cbegin(n) //与5同,const迭代器
- p=c.cend(n) //与6同,const迭代器
-
容器适配器提供受限的特殊接口,不直接访问底层容器,不提供迭代器和下标操作
-
stack,queue, priority_queue
三十二章 STL 算法
-
不修改序列的算法
- f=for_each(b, e, f) //对[b,e)中的每个元素x执行f(x);返回f
- 序列谓词
- all_of(b,e,f) // [b,e)中所有x都满足f(x)?
- any_of(b,e,f)// [b,e)中某个x都满足f(x)?
- none_of(b,e,f)// [b,e)中所有x都不满足f(x)?
- count
- x=count(b,e,v)//x为 *p==v的元素数量
- x=count_if(b,e,f) //满足f(*p)的元素数量
- find搜索具有特定值或令谓词为真的元素
- p=find(b,e,v) //p指向[b:e)中第一个满足*p==v的元素
- p=find_if(b,e,f) //与1同, f(*p)
- p=find_if_not(b,e,f) //与2同,!f(*p)
- p=find_first_of(b,e,b2,e2) //第一个满足 *p==*q, q指向[b2:e2)中的某个元素
- p=find_first_of(b,e,b2,e2,f) //与4同,f(*p,*q)
- p=adjacent_find(b,e) //第一个满足*p==*(p+1)
- p=adjacent_find(b,e,f) //与6同, f(*p, *(p+1))
- p=find_end(b,e,b2,e2) //最后一个满足*p == *q, q指向第二个序列中的某个元素
- p=find_end(b,e,b2,e2,f) // 与8同,f(*p, *q)
- equal和mismatch
- equal(b,e,b2) //所有元素相等v==v2?
- equal(b,e,b2,f) //所有元素满足f(v,v2)?
- pair(p1,p2) = mismatch(b,e,b2) //p1指向第一个满足!(*p1==*p2)的元素,否则p1==e
- pair(p1,p2) = mismatch(b,e,b2,f)//与3同,!f(*p1, *p2)
- search()查找给定序列是否是另一个序列的子序列
- p=search(b,e,b2,e2)//p指向[b:e)中第一个满足[p:p+(e2-b2)) 等于[b2:e2)的*p
- p=search(b,e,b2,e2,f) // 与1同,使用f比较
- p=search(b,e,n,v) //p指向[b:e) 中第一个满足[p:p+n)间所有元素值均为v的位置
- p=search(b,e,n,v,f)//与3同,使用f(*p, v)比较
-
修改序列的算法
-
p=transform(b,e,out,f)//对每个元素应用f,写到out, p==out+(e-b)
-
p=transform(b,e,b2,out,f)//对两个序列的元素应用f(*p1,*p2), 结果写入out, p==out+(e-b)
-
copy():只有当两个序列不重叠或输出序列的末尾位于输入序列内部时,才可以使用copy
- p=copy(b,e,out) //拷贝所有元素到out; p==out+(e-b)
- p=copy(b,e,out,f) //将满足f(x)的元素x拷贝到[out:p)
- p=copy(b,n,out) //拷贝n个元素,p==out+n
- p=copy_backward(b,e,out) //与1同,从尾元素开始拷贝
- p=move(b,e,out)//与1同,使用移动操作
- p=mov_backward(b,e,out) //与5同,从尾元素开始移动
-
unique
- unique(b,e)//移动[b,e)中的一些元素,是的[b,p)中无连续重复元素
- unique(b,e,f) //与1同,使用f(*p,*(p+1))判断是否重复
- unique_copy(b,e,out) //拷贝元素到out,不拷贝连续重复元素
- unique_copy(b,e,out,f)//与3同,不拷贝连续重复元素,使用f(*p, *(p+1))判断重复
-
remove, replace
- p=remove(b,e,v) //删除值为v的元素
- p=remove_if(b,e,f) //删除满足f(*p)的元素
- p=remove_copy(b,e,out,v) //拷贝不为v的元素
- p=remove_copy_if(b,e,out,f) //拷贝不满足f(*p)的元素
- reverse(b,e) //逆序排列
- reverse_copy(b,e,out) //逆序拷贝
- replace(b,e,v,v2)
- replace(b,e,f,v2)
- p=replace_copy(b,e,out,v,v2)
- p=replace_copy_if(b,e,out,f,v2)
-
rotate(), random_shuffle, portition()
- p=rotate(b,m,e) //循环左移:将[b:e)看作一个环,*(b+i)移动到、*((b+(i+(e-m))%(e-b))
- p=rotate_copy(b,m,e,out):循环左移拷贝到out
- random_shuffle(b,e) //洗牌b,e中的元素,使用默认随机数发生器
- random_shuffle(b,e,f) //使用随机数发生器f
- shuffle(b,e,f) //使用均匀分布随机数发生器f
- p=partition(b,e,f)//满足f(*p)的元素置于区间[b:p), 其他元素置于[p:e)
- p=stable_partition(b,e,f)//与6同,保持相对顺序
- pair(p1,p2)=partion_copy(b,e,out1,out2,f)//满足f(*p)的元素拷贝到[out1:p1), 否则拷贝到[out2:p2)
- p=partition_point(b,e,f) //p指向满足all_of(b,p,f)且none_of(p,e,f)
- Is_partition(b,e,f) // 满足f(*p)的元素都在!f(*p)之前吗?
-
排列:生成一个序列的所有排列,若next_*或prev_*操作成功返回true,否则返回false
- x=next_permutation(b,e)//将[b,e)变换为字典序上的下一个排列
- x=next_permutation(b,e,f)//与1同,用f比较元素
- x=prev_permutation(b,e) //前一个排列
- x=prev_permutation(b,e,f)//使用f比较元素
- is_permutation(b,e,b2) //判断b2序列是否是[b,e)的一个序列
- is_permutation(b,e,b2,f)//与5同,用f比较
-
fill 向序列元素赋值和初始化元素
- fill(b,e,v) //赋值
- fill_n(b,n,v)
- generate(b,e,f)//将f()赋予每个元素, 赋值
- p=generate_n(b,n,f) // p==b+n
- uninitialized_fill(b,e,v) //初始化
- p=uninitialized_fill_n(b,n,v) // p==b+n
- p=uninitialized_copy(b,e,out) // 用b,e中的元素初始化out序列元素,p==out+(e-b), 目标元素必须是内置类型或未初始化的
- p=uninitialized_copy_n(b,n,out) //p=out+n
-
swap
- swap(x,y)
- swap_ranges(b,e,b2)//对每个元素调用swap(v,v2)
- Iter_swap(p,q) // swap(*p,*q)
-
排序和搜索, sort要求随机访问迭代器
-
sort(b,e)
-
sort(b,e,f)
-
stable_sort(b,e) //保持相等元素相对顺序
-
stable_sort(b,e,f)
-
partial_sort(b,m,e) //部分排序,[b,m)有序即可
-
partial_sort(b,m,e,f)
-
partial_sort_copy(b,e,b2,e2)//部分排序[b,e), 排好前e2-b2个元素,拷贝到[b2,e2); p为e2和b2+(e-b)的较小者
-
partial_sort_copy(b,e,b2,e2,f)//同7
-
is_sorted(b,e)
-
is_sorted(b,e,f)
-
p=is_sorted_until(b,e) //p指向第一个不符合升序的元素
-
p=is_sorted_until(b,e,f)
-
nth_element(b,n,e)//*n的位置恰好是[b,e)排序后它应处的位置,即[b,n)中的元素都<=*n, 且[n,e)中的元素都>=*n
-
nth_element(b,n,e,f)
-
排序C风格字符串需要一个显示的比较标准
-
-
二分搜索,提供有序序列上的二分搜索,只需要前向迭代器
- p=lower_bound(b,e,v)//p指向v首次出现的位置,如果没有找到,p指向第一个大于v的元素或者e
- p=lower_bound(b,e,v,f)
- p=upper_bound(b,e,v)//p指向第一个大于v的元素
- p=upper_bound(b,e,v,f)
- binary_search(b,e,v) //v在有序序列[b,e)中吗?
- binary_search(b,e,v,f)
- pair(p1,p2)=equal_range(b,e,v)//[p1,p2)是值为v的子序列,通常用二分搜索查找v
- pair(p1,p2)=equal_range(b,e,v,f)
-
merge,将两个有序序列合并为一个,可接受不同类别的序列和不同类型的元素:
-
p=merge(b,e,b2,e2,out)
-
p=merge(b,e,b2,e2,out,f)
-
inplace_merge(b,m,e)//原址合并,将两个有序序列[b,m), [m,e)合并为有序序列[b,e)
-
inplace_merge(b,m,e,f)
-
例子:
vector
v{3,1,2,4}; list
lst{0.5, 1.5, 2, 2.5} sort(v.begin(), b.end());
Vector_double v2;
merge(v.begin(), v.end(), lst.begin(), lst.end(), back_inserter(v2));
-
-
集合算法
- includes(b,e,b2,e2). //b,e中的所有元素都在b2,e2中?
- includes(b,e,b2,e2,f)
- p=set_union(b,e,b2,e2,out)//创建一个有序序列[out,p),包含两个序列所有元素
- p=set_union(b,e,b2,e2,out,f)
- p=set_intersection(b,e,b2,e2,out)//同3,包含两个序列共同元素
- p=set_intersection(b,e,b2,e2,out,f)
- p=set_difference(b,e,b2,e2,out)//同3,在b,e中但不在b2,e2中的元素
- p=set_difference(b,e,b2,e2,out,f)
- p=set_symmetric_difference(b,e,b2,e2,out)//同3,在b,e或b2,e2 中,但不同在两者中
- p=set_symmetric_difference(b,e,b2,e2,out,f)
-
堆—>最大值优先
- make_heap(b,e)
- make_heap(b,e,f)
- push_heap(b,e)//将*(e-1)添加到堆[b,e-1),是的b,e还是一个堆
- push_heap(b,e,f)
- pop_heap(b,e) // 删除最大值,[b,e-1)仍然是堆
- pop_heap(b,e,f)
- sort_heap(b,e) //排序堆
- sort_heap(b,e,f)
- is_heap(b,e)
- is_heap(b,e,f)
- is_head_until(b,e)//p是满足[b,p)是堆的最大位置
- is_heap_until(b,e,f)
-
最大值和最小值
- x=min(a,b), max(a,b)
- x=min(a,b,f), max(a,b,f)
- x=min({elem}), max({elem})
- x=min({elem},f), max({elem},f)
- pair(x,y)=minmax(a,b)
- pair(x,y)=minmax(a,b,f)
- pair(x,y)=minmax({elem})
- pair(x,y)=minmax({elem},f)
- p=min_element(b,e)
- p=min_element(b,e,f)
- p=max_element(b,e)
- p=max_element(b,e,f)
- pair(x,y)=minmax_element(b,e) //x,y为迭代器
- pair(x,y)=minmax_element(b,e,f)
-
三十三章 迭代器
-
迭代器类别
- 输入迭代器:istream : ++, *, ==, !=, ->, 单一读
- 输出迭代器:ostream: ++, *, 单一写
- 前向迭代器:forward_list: ++, *, ->, ==, !=, 反复读写
- 双向迭代器: list, map, set: ++, - -, *, ->, ==, !=
- 随机访问迭代器: vector: [], +, +=, -, -=, <, <=, >, >=,++, - -, *, ->, == , !=
-
迭代器萃取
-
iterator_traits
//非指针Iter的萃取类型 -
iterator_traits<T*> //指针T*的萃取类型
-
input_iterator_tag //输入迭代器类型
-
output_iterator_tag //输出迭代器类型
-
forward_iterator_tag //派生自input_iterator_tag
-
bidirectional_iterator_tag //派生自forward_iterator_tag
-
random_access_iterator_tag //派生自bidirectional_iterator_tag
-
tag的本质是类型,可用于标签分发,如:
template< typename Iter>
void advance_helper(Iter p, int n, random_access_iterator_tag){
p += n;
}
template< typename Iter>
void advance_helper(Iter p, int n, forward_iterator_tag){
if(0<n)
while(n—) ++p;
else if(n<0)
while(n++) —p;
}
template< typename Iter>
void advance(Iter p, int n){. //使用最优算法
return advance_helper(p, n, iterator_traits< Iter>::iterator_category{});
}
-
-
迭代器操作
- p++
- ++p
- *p
- –p
- p–
- p[n]
- p->m
- p==q
- p!=q
- p<q
- p<=q
- p>q
- p>=q
- p+=n
- p-=n
- q=p+n
- q=p-n
- advance(p,n) //p+=n,p至少是一个输入迭代器
- x=distance(p,q)// x=q-p,p至少是一个输入迭代器
- q=next(p,n) //p至少是一个前向迭代器,q=p+n
- q=next(p) // q=p+1
- q=prev(p,n)// q = p-n,p至少是一个双向迭代器
- q=pre(p)// q = p-1
-
迭代器适配器
- reverse_iterator //反向遍历
- back_insert_iterator //尾部插入
- front_insert_iterator //头部插入
- insert_iterator //任意位置插入
- move_iterator // 移动而非拷贝
- raw_storage_iterator //写入未初始化的存储空间
-
一个反向迭代器与其底层迭代器之间的根本关系:&*(reverse_iterator(p)) == &*(p-1), 可理解为反向迭代器使用正向迭代器实现
-
对一个reverse_iterator,ri.base()返回一个iterator,指向ri之后的位置;即prev(ri.base())与ri指向相同的元素
-
插入迭代器,当写数据时,插入器将新元素插入序列而不是覆盖已有元素,防止溢出。
-
插入器构造函数
- ii=inserter(c,p) //ii是一个insert_iterator,指向容器c中的p,在p之前插入
- ii=back_inserter(c) //ii是back_insert_iterator, 指向c的back()
- ii=front_inserter(c)//ii是front_insert_iterator, 指向c的front()
-
一个插入器是一个输出迭代器,不能通过插入器读取数据, insert_iterator
操作: - insert_iterator p{c, q}// 为容器c构造一个插入器,指向*q, q必须指向c
- insert_iterator p{q} //拷贝构造函数
- p=q
- p=move(q)
- ++p //令p指向下一个元素
- p++
- *p=x //在p之前插入x
- *p++=x //在p之前插入x,然后递增p
-
移动迭代器:通过移动迭代器读取元素时会移动元素而非拷贝元素,其构造函数:
mp=make_move_iterator(p)//mp是一个移动迭代器,指向p所指元素
移动迭代器的operator*()简单返回元素的右值:std::move(q). 例如:
vector
read_strings(istream&); auto vs = read_strings(cin);
vector
vs2, vs3; copy(vs, back_inserter(vs2)) //从vs向vs2拷贝元素
copy(vs2, make_move_iterator(back_inserter(vs3)))//从vs2向vs3移动元素
-
范围访问函数:标准库为容器提供了非成员版本的begin(), end()
- p=begin(c) //p是指向容器c的首元素的迭代器,c是一个数组或具有c.begin()
- p=end(c)//p是指向容器c的尾后位置的迭代器,c是一个数组或具有c.end()
- 只要通过#include 包含了
, 具有begin(),end()成员的用户自定义容器就会自动获得非成员版本
-
函数对象,在< functional>中,标准库提供了若干常用函数对象
- equal_to
(x,y). // x==y - not_equal_to
(x,y). //x!=y - greater
(x,y). //x>y - less
(x,y). //x<y - greater_equal
(x,y) //x>=y - less_equal
(x,y). // x<=y - logical_and
(x,y)// 总是对两个参数都求值, x&&y - logical_or
(x,y) // 总是对两个参数都求值, x||y - logical_not
(x) // !x - bit_and
(x,y) // x & y - bit_or
(x,y) // x|y - bit_xor
(x, y) // x^y - f=plus
(x, y). //x+y - f=minus
(x,y). //x-y - f=multiplies
(x,y). //x*y - f=divides
(x,y). //x/y - f=modulus
(x,y). //x%y - f=negate
(x). //. -x
- equal_to
-
函数适配器:接受一个函数参数,返回一个可用来调用该函数的函数对象
- g=bind(f,args)//g(args2) 等价于f(args3), args3使用args2中的实参替换args中对应的占位符(如_1, _2, _3)得到的,占位符在namespace placeholders中
- g=mem_fn(f)//若p是一个指针,g(p,args)表示p->f(args), 否则表示p.mf(args),args可能为空
- g=not1(f) // g(x) == !f(x)
- g=not2(f) // g(x,y) == !f(x,y)
-
bind()
-
重载函数的绑定需要指定绑定的是哪个函数:
int pow(int, int)
double pow(double, double)
auto pow2 = bind(pow, _1,2) //错误, 绑定哪个pow?
auto pow = bind((double(*)(double, double))pow, _1, 2)
-
bind接受普通表达式作为参数,对引用参数而言,bind看到他们之前已被解引用。可使用ref(t), cref(t)传递引用参数
-
-
mem_fn(mf)生成一个函数对象,可以作为非成员函数调用,面向对象调用到函数式调用风格的映射。
void user(Shape* p){
p->draw();
auto draw = mem_fn(&Shape::draw);
draw(p);
}
-
function, 是一种类型,可以保存能用调用元算符()调用的任何对象,如普通函数,函数对象,lambda等