04.08_111期_C++_reverseiterator实现和理解

priority_queue这个类中的top()获得的是数据较大的优先级高,

priority_queue其底层实现就是一个大根堆

priority_queue<int> pq;

传入以下的模板参数,其中 greater<int> 保证了 生成的 pq 对象是小根堆

greater<int>为仿函数

vector<int> v = { 3, 1, 7, 4, 6, 3 };

//升序

sort(v.begin(), v.end());

for (auto e : v)

{

cout << e << " ";

}

cout << endl;

降序: 要借助仿函数greater<int>,可以使用几种方法

第一种:使用具体的实例化对象

greater<int> gt;

sort(v.begin(), v.end(), gt);

第二种 匿名对象

这里之所以使用了greater<int>()创建一个属于 greater<int>类 的匿名对象

是因为sort是一个函数,其参数的类型都是函数模板给出的,所以传入参数时要给确切的实例化对象

仿函数就是一个普通的类

这个类创建出来的实例可以像函数名一样,对()内进行传实参后使用

这个类对()这个运算符进行重载,使得下面两种用法相等

  1. 实例化对象.operator()(参数1, 参数2, ...)

  2. 实例化对象(参数1, 参数2, ...)

priority_queue这个类中的top()获得的是数据较大的优先级高,

priority_queue其底层实现就是一个大根堆

priority_queue<int> pq;

传入以下的模板参数,其中 greater<int> 保证了 生成的 pq 对象是小根堆

greater<int>为仿函数

下面三种push元素的方式:

方式一:先创建一个Date的实例,再用这个实例进行push

方式二:生成一个匿名对象之后,将这个匿名对象进行push

方式三:隐式类型转换,生成临时对象之后,将这个匿名对象进行push

为什么以下函数给第三个位置直接传了一个 名叫GreaterPDate的形参

  1. 如果直接传入bit::greater<Date*>,

是无法调到bool Date::operator>(const Date& d) const 这个函数的

因为Compare com; 这句话实际上是执行了 greater<Date*> com;这句话

com(_con[parent], _con[child]); 这句话实际上就执行了 greater类中的函数 operator()

而且传入参数时是执行

bool operator()(const Date* x, const Date* y)

{

return x > y;

}

以上函数在执行到 return x > y; 这句话时

那么就要调用 Date类中的 operator> 这个函数,对应执行的是

可此时的函数的形参类型是 const Date& 类型,不是const (Date*)& d 类型

  1. 在main函数上方直接定义一个函数,如果函数声明是

σ:bool operator<(const Date* d1, const Date* d2); 同样不能使用

bit::priority_queue<Date*, vector<Date*>, bit::greater<Date*>> pqptr;这句话

因为无论什么类型,只要加上了 * 号,就变成了指针类型的变量,

就一定是一个内置类型的变量,那么σ处的声明就完全没有用到自定义类型

此时的运算符重载就不符合语法规定,

语法规定要对 >, <, ==, != 这一类的逻辑运算符进行重载时,

声明的参数列表中至少要有一个自定义类型的参数

  1. 如果非要在优先级队列中传入Date*作为模板参数,只能使用仿函数的方法

在优先级队列的逻辑中不像 2. 那样去重新重载专门属于Date* 的比较逻辑

而是通过com这个实例对应的类是一个如下的仿函数

其中 return *p1 > *p2; 这句话中的 > 还是

调用了Date这个类中的bool Date::operator>(const Date& d) const这个函数

class GreaterPDate

{

public:

bool operator()(const Date * p1, const Date * p2)

{

return *p1 > *p2;

}

};

而在执行到com(_con[parent], _con[child])这个代码

可以通过GreaterPDate这个类中对 () 进行重载的操作符

即通过这个运算符调用bool operator()(const Date * p1, const Date * p2)这个函数

通过上面的分析可知,仿函数可以在函数要执行不同的逻辑时调用不同的函数

priority_queue是容器适配器,只是与stack, queue 这另外两种适配器不同的是,

priority_queue还需要仿函数参数控制大根堆和小根堆

bit::queue<int> st;

st.push(1);

st.push(2);

st.push(3);

st.push(4);

st.push(5);

printf("size: %d\n", st.size());

for (size_t i = 0; !st.empty(); i++)

{

if (!st.empty())

{

cout << st.front() << " ";

st.pop();

}

}

cout << endl;

Less<int> ls;

下面这几句话是等价的

cout << ls(1, 2) << endl;

cout << ls.operator()(1, 2) << endl;

cout << Less<int>()(1, 2) << endl;

cout << Less<int>().operator()(1, 2) << endl;

这个文件σ设计一个对应任意容器的反向迭代器

也就是迭代器适配器

既然是适配器,那么只要模板参数确定,这个适配器类就要有对应的属性

这样就不用在每个容器类的内部专门都定义一个反向迭代器的行为了

每个容器要使用 反向迭代器 都是调用σ中的迭代器类,

然后调用文件σ中对应的反向迭代器

而这个 反向迭代器类 中的所有运算符重载成员函数

都是调用 正向迭代器 的类中的已经重载过的运算符

ReverseIterator这个类在实现时要达到的效果是:

只要有一个具体的容器类的正向迭代器,就能获得属于这个容器类的 反向迭代器

比如给 list<T>::iterator,经过这个类就得到 list<T>::ReverseIterator

在STL中实现的形式就是:

typedef __list_iterator<T, T&, T*> iterator;

typedef __list_iterator<T, const T&, const T*> const_iterator;

typedef reverse_iterator<iterator> reverse_iterator;

typedef reverse_iterator<const_iterator> const_reverse_iterator;

相关推荐
Uitwaaien5411 分钟前
51 单片机矩阵键盘密码锁:原理、实现与应用
c++·单片机·嵌入式硬件·51单片机·课程设计
小唐C++44 分钟前
C++小病毒-1.0勒索
开发语言·c++·vscode·python·算法·c#·编辑器
Golinie2 小时前
【C++高并发服务器WebServer】-2:exec函数簇、进程控制
linux·c++·webserver·高并发服务器
课堂随想2 小时前
`std::make_shared` 无法直接用于单例模式,因为它需要访问构造函数,而构造函数通常是私有的
c++·单例模式
Zfox_2 小时前
应用层协议 HTTP 讲解&实战:从0实现HTTP 服务器
linux·服务器·网络·c++·网络协议·http
OliverH-yishuihan2 小时前
C++ list 容器用法
c++·windows·list
Forest_HAHA3 小时前
14,c++——继承
开发语言·c++
可涵不会debug3 小时前
C语言文件操作:标准库与系统调用实践
linux·服务器·c语言·开发语言·c++
刘好念3 小时前
[OpenGL]实现屏幕空间环境光遮蔽(Screen-Space Ambient Occlusion, SSAO)
c++·计算机图形学·opengl·glsl
C嘎嘎嵌入式开发5 小时前
什么是僵尸进程
服务器·数据库·c++