C++候捷stl-视频笔记3

算法的形式

在这里插入图片描述
Cmp通常是个比大小的准则,是Functor。
算法所需的信息通常指迭代器如何移动

迭代器的分类

在这里插入图片描述
array,vector,deque它们是连续的,它们的迭代器是Random Access Iterator/随机访问迭代器
list的迭代器是Bidirectional Iterator/双向迭代器
forward_list的迭代器是Forward Iterator/前向迭代器
基于红黑树的set/multiset, map/multimap它们都是Bidirectional Iterator
基于hashtable的unordered_set, unordered_multiset, unordered_map, unordered_multimap的迭代器是双向的(Bidirectional Iterator)还是单向的(Forward Iterator),要看bucket对应的链表具体是双向链表还是单向链表。具体到STL应该是forward_iterator
在这里插入图片描述
根据分类自己打印各容器的迭代器类型字符串
在这里插入图片描述
利用c++本身typeid打印出迭代器类型
在这里插入图片描述
父类没有数据和函数,只有typedef。目的是为了让子类拥有这些别名,方便写代码
在这里插入图片描述

迭代器分类对算法的影响

在这里插入图片描述
distance:知道两个指针的距离,相当于两个指针相减。如果无法相减,只能循环

typename 的使用是为了指定 iterator_traits<_InputIterator>::difference_type 表示一个类型。iterator_traits<_InputIterator>::difference_type 是迭代器 _InputIterator 的差值类型(表示两个迭代器之间的距离),而 typename 在这里是为了明确告诉编译器这是一个类型而不是其他类型的标 识符
在这里插入图片描述
advance函数会根据iterator_category(__i)的类型选择调用不同的__advance的实现

容器迭代器的分类是基于对象(存在继承关系),而不是基于enum(枚举类型)

迭代器虽然有5种,但根据继承关系(子类is a 父类),只要实现了父类,不需要5种都实现
在这里插入图片描述
copy会不断地做检查,检查是否为某种迭代器,决定copy是否要做某些操作来加速
traits区分赋值拷贝重不重要,如复数类,没有指针不重要
在这里插入图片描述
destroy和前面类似,不断细分类型。traits区分析构函数重不重要
在这里插入图片描述
在这里插入图片描述
unique_copy例子
在这里插入图片描述
算法是模板函数,可以接收任意类型的参数,语法没法指定传入的参数类型
因此在定义模板参数名称的时候,会命名(暗示)它想要接收的类型,比如下图,distance函数想要接收的是input iterator,而sort想要接收的是random access iterator,rotate函数想要接收forward iterator等等

算法源码剖析

在这里插入图片描述
C++标准库提供的algorithm需要符合如下接口

template<typename Iterator>
std::Algorithm(Iterator itr1, Iterator itr2, ...)
{
    ...
}

在这里插入图片描述
一般函数都有两个版本,第二个版本一般是允许增加一种原则或者操作,从而应用的更广泛

myobj是个函数对象,是myclass类,重载了()
在这里插入图片描述
for_each让范围里的所有元素都依次做同一件事情
在这里插入图片描述
replace:范围内的所有等于 old_value 的,都被 new_value 取代
replace_if:范围内所有满足 pred() 为 true 的元素都被 new_value 取代
replace_copy:范围内的元素全部 copy 到新地方,其中所有等于 old_value 的,都被替代为 new_value
在这里插入图片描述
count:在范围中计数值等于 value 的个数
count_if:在范围中计数满足条件 pred() 的个数
所有关联式容器自带成员函数 count()
在这里插入图片描述
find:在范围内找到值等于 value 的元素
find_if:在范围内找到满足 pred() 的元素
所有关联式容器自带成员函数 find()
在这里插入图片描述
所有关联式容器((本身就排好序了)没有成员函数 sort(),array,vector,deque也没有
list、forward_list无法跳跃,因此只能使用自带sort
在这里插入图片描述
逆向迭代器,rbegin()使用end(),然后套用一个reverse_iterator适配器
在这里插入图片描述
二分查找是否存在目标元素(并不给予位置),使用前必须先排序;主要使用 lower_bound() 来找到能放入 val 的最低位置,再判断该元素是否存在

仿函数和函数对象

仿函数只为算法服务,提供一些特殊准则
在这里插入图片描述
在这里插入图片描述
GC++独有的仿函数
在这里插入图片描述
sort仿函数
在这里插入图片描述
STL中的每个仿函数都继承了binary_function<T, T, bool>,表示有两个操作数的操作,共3个模版参数,对应的还有unary_function,表示有1个操作数的操作(如否定)

如果希望自己写的仿函数可以修改,适配,融入stl,就需要继承上述两个结构之一因为adpat可能向functors提问上述三个别名

仿函数就是一个class里头的重载小括号,这样的class创建的对象就是函数对象/仿函数,因为做出来的是一个对象但像一个函数

存在多种Adapter

迭代器适配器(Iterator Adapters):用于在不同迭代器之间进行转换或提供额外功能的适配器。例如,std::back_inserter、std::front_inserter、std::inserter 等。
函数适配器(Function Adapters):用于在函数对象之间进行转换或提供额外功能的适配器。例如,std::bind、std::function 等。
容器适配器(Container Adapters):提供不同接口的容器,例如,std::stack、std::queue、std::priority_queue 等

改造例子:stack 中将 deque 的 push_back 改名为 push

函数适配器

binder2nd

在这里插入图片描述
binder2nd是函数适配器之一,用于将一个二元操作函数(_Operation)和一个固定的值(__y)绑定在一起 —— 绑定第二参数

binder2nd类继承自unary_function,表示其为一元函数对象,其operator()用于执行绑定的操作
在这里插入图片描述

not1

在这里插入图片描述

bind

在这里插入图片描述
占位符 placeholders:
using namespace std::placeholders;
提供了 _1,_2,_3,·······
上面的的 _1 指的是被绑函数中的第一个参数

// functions
double my_divide(double x, double y)
{
	return x/y;
}

// function objects 测试与functions同理
// divides<double> my_divide;

struct MyPair
{
    // data members
	double a, b;
    // member functions
	double multiply()
	{
		return a*b;
	}
};

auto fn_five = bind(my_divide, 10, 2);
cout << fn_five() << endl; // 5.0

auto fn_half = bind(my_divide, _1, 2);
cout << fn_half(10) << endl; // 5.0

auto fn_invert = bind(my_divide, _2, _1);
cout << fn_invert(10, 2) << endl; // 0.2

//将 my_divide 的返回类型变为 int,即 int(x/y)
auto fn_rounding = bind<int>(my_divide, _1, _2); 
cout << fn_rounding(10, 3) << endl; // 3

MyPair ten_two {10, 2};  //定义一个实例ten_two
//绑定 member functions,由于成员函数有 this,所以 _1 就相当于 this,即 x.multiply()
auto bound_memfn = bind(&MyPair::multiply, _1);
cout << bound_memfn(ten_two) << endl; // 20

//把实例 ten_two 绑定到 a,即 ten_two.a
auto bound_memdata = bind(&MyPair::a, ten_two);
cout << bound_memdata() << endl; // 10

auto bound_member_data2 = bind(&MyPair::b, _1);
cout << bound_member_data2(ten_two) << endl;

迭代器适配器

reverse_iterator

在这里插入图片描述
对逆向迭代器取值,就是取其所指正向迭代器的前一个位置

inserter

在这里插入图片描述
对于 copy(InputIterator first, InputIterator last, OutputIterator result),其会不管 OutputIterator 后是否有充裕空间,对 result 开始依次赋值
因此对=操作符重载,将iterator的赋值操作改变为insert操作,如上图下面部分

ostream_iterator

ostream适配器,因为是为了改造basic_ostream
用于将数据输出到输出流(ostream)。它是一个模板类,通常用于将容器中的元素输出到输出流,或者将其他可输出的数据类型输出到流中
在这里插入图片描述
将 copy 变为一个输出工具,分隔符是 ,
其核心依然是操作符重载,这样就相当于 cout<<*first; cout<<“,”;

istream_iterator

用于从输入流(istream)中读取数据。它是一个模板类,通常用于从输入流中读取数据到容器中,或者直接读取输入流中的数据
在这里插入图片描述在创建 iit 的时候就已经把所有的键盘输入读进去了,之后就是一个一个取出来赋值给 value 的操作
++iit; 语句用于使 istream_iterator 前进到输入流的下一个元素。
在这里插入图片描述
copy和istream iterator适配器,对操作符进行重载,实现和cin的同步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值