05 | 容器汇编 II:需要函数对象的容器
函数对象及其特化
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了C++中的函数对象以及需要函数对象的容器,以及关联容器和无序关联容器的使用方法和特点。文章首先讨论了`less`和`hash`两个重要的函数对象,分别用于比较大小关系和计算哈希值,并通过代码示例展示了它们的基本用法和特点。接着介绍了`priority_queue`容器适配器,演示了如何使用它以及如何传递不同的比较函数对象来改变容器的行为。随后,文章详细介绍了关联容器和无序关联容器的特点和使用方法,包括`set`、`map`、`multiset`、`multimap`、`unordered_set`、`unordered_map`、`unordered_multiset`和`unordered_multimap`等容器的特性和区别。通过代码示例展示了这些容器的基本操作和特点,以及如何使用自定义的哈希函数对象。总的来说,本文通过深入讲解函数对象和不同类型的容器,帮助读者全面了解了C++中的容器和函数对象的使用方法和特点,以及关联容器和无序关联容器的区别和优劣势。 文章还介绍了C++的两个常用的函数对象`less`和`hash`,以及用到这两个函数对象的容器适配器、关联容器和无序关联容器。最后,通过例子展示了为什么我们应当避免C数组而考虑使用`array`。通过这些内容,读者可以完整地了解C++提供的标准容器。 在阅读本文后,读者可以快速了解C++中函数对象和不同类型的容器的使用方法和特点,以及关联容器和无序关联容器的区别和优劣势。同时,读者还可以了解到为什么应该避免使用C数组,而考虑使用`array`。这篇文章对于想要深入了解C++容器和函数对象的读者来说是一份有价值的资料。
《现代 C++ 编程实战》,新⼈⾸单¥59
全部留言(24)
- 最新
- 精选
- 糖1. 首先是为了遍历容器方便,其次为了保证std接口的一致性 2. 我认为是没有必要的,因为,如果用类的继承一般会产生虚函数,这也就导致多存储一个虚函数表,在内存上产生了不必要的浪费。
作者回复: 基本正确。 2 实际上还是因为这儿继承真的没啥用。有了泛型,继承基本是种浪费。而且,继承用基类的指针或引用才有用,而C++里的容器类一般都是当值类型来用的。
2019-12-07322 - 皓首不倦老师您好 第一个问题个人觉得提供出头尾迭代器目的主要是提供给STL算法库用,STL算法库实现是只认迭代器的,这样的设计可以避免算法实现和具体容器类型的强耦合 第二个问题个人觉得是因为各种容器API和功能上差异比价大,难以做一层比较通用的抽象,但是像map和unordered_map这样功能比较相近的容器我觉的还是可以做一层抽象的,像Java中TreeMap和HashMap就同时实现了Map接口,做了一层抽象,其实我也一直没有弄懂C++为什么没有向Java一样对功能相近的容器做一层接口的抽象层,老师能帮我解答下吗?
作者回复: 一,正确。 二,问题还在于C++的值语义。如果你用一个 AbstractMap来访问map和unordered_map,你只能用引用或指针,并不方便。而且,map和unordered_map的模板参数还不一样,通用的话反而成了阉割版……
2019-12-0929 - qinsi既然关联容器的key需要满足strict weak ordering,那么sort的比较函数是不是也需要满足?比如sort(v.begin(), v.end(), less_equal<int>());是否可行?
作者回复: 是,也必须满足。标准里明确这么要求了。 如果你传了 less_equal 这样的条件,结果可能是正确,也可能是错误,也可能是程序崩溃。具体发生什么,取决于排序算法的实现。出了问题,就是调用者的锅,不是 sort 的 bug。 以冒泡排序为例,我试了一下,如果是用检验有没有交换来决定是否退出排序,那么,在元素有重复的情况下使用 less_equal 来排序,会导致死循环。
2019-12-077 - 啦啦啦想问一下,priority_queue这种,如果通过指针持有某个对象,然后传入比较函数,那么如果更新指针指向对象的值,priority_queue是否会更新?如果不会,有方法能够使它更新吗?
作者回复: 不会也不可以。这些容器适配器不提供遍历的迭代器就是不允许像你描述这样的任意访问。(迭代器就是广义指针。)
2019-12-104 - lyfei老师你好,那为什么unodered_map会使用到operator==的呢? 我感觉他不是应该把数据转到hash值,然后保存起来,也感觉没有比较的过程,哪个地方体现了==这个运算符呀?
作者回复: 不是。哈希是哈希,哈希可能有冲突的,相同哈希值也要看键是相同还是不同,来决定是覆盖还是加一项。去看一下数据结构里面的哈希。
2019-12-0823 - 中年男子1、begin、end是迭代器,主要用于对不同类型的容器提供统一的遍历容器的辅助 2不同容器内存分配方式不同,实现不同,基类方法无法做到统一,非要用继承只能定义虚函数 多用组合、少用继承(抖个机灵)
作者回复: 哈哈,是这样的。
2019-12-063 - 李义盛2.继承是强耦合。 继承导致关系混乱。
作者回复: 算是一个点。真要继承,不会更好用,因为容器的接口差异往往很小,这儿多一个,那儿少一个,要多少接口才能表达啊。
2019-12-063 - 贾陆华1. 看到一个注释笔误,是从大到小吧 // 从小到大排序 sort(v.begin(), v.end(), greater<int>()); cout << v << endl; 2. map.lower_bound(k)默认代表的意思是找到第一个x,x不小于k,map.upper_bound(k)默认是找到第一个x,x大于k,为什么不是x小于k,upper_bound字面意思不是上界吗?
作者回复: 1. 哈,还真是的。典型的拷贝粘贴错误…… 2. 想一想,C++ 里到处是半开半闭区间。右界一直是会超出有效范围的。
2019-12-0722 - 爱笑的布谷鸟请问老师,为什么 weak_ptr 不能作为 unordered_x 容器的 key?
作者回复: weak_ptr里你要获取指针都得去lock一下,你该怎么去算哈希值和判断相等?不能算哈希值和判断相等,你以后怎么做查询?
2022-09-01归属地:上海1 - Geek_24c4df看不懂下面用法 unordered_map<complex<double>, double> umc{{{1.0, 1.0}, 1.4142}, {{3.0, 4.0}, 5.0}}; 为什么键里面还要套一层大括号数据
作者回复: {1.0, 1.0} 可以用来构造一个复数(1 + i),{{1.0, 1.0}, 1.4142} 是 unordered_map 里的一项。
2020-05-231