引述
使用
map<string,int> ma;
[]
算符访问键值,如
ma["Hello"]=1;
但是multimap访问键值就没那么方便了,multimap允许键重复,即同一键可能对应多个键值,因而multimap取消了
[]
算符.
通常已知键遍历multimap中的所有对应键值的方法有很多种,这是一种常用的方法
multimap<string,int> mb;
auto it=mb.equal_range("key");
for(auto& i=it.first;i!=it.second;i++){
cout<<i->second<<", ";
}
可以看到这个方法显式地使用了迭代器.
但说起遍历,最优美的遍历方法应当是使用 范围for , 范围for隐藏了迭代器
范围for
cppreference 提到 范围for
for ( 范围声明 : 范围表达式 ) 循环语句
{
auto && __range = 范围表达式 ;
for (auto __begin = 首表达式, __end = 尾表达式;
__begin != __end; ++__begin) {
范围声明 = *__begin;
循环语句
}
}
其中,__range , __begin 和 __end 仅用于说明内容,首表达式 与 尾表达式 定义如下:
- 若 范围表达式 是数组类型表达式,则 首表达式 为
__range
而 尾表达式 为(__range + __bound)
,其中__bound
是数组的元素数目(若数组大小未知或拥有不完整类型,则程序不合法) - 若 范围表达式 是拥有名为
begin
以及end
成员的类类型 C 的表达式(不管该成员的类型或可见性),则 首表达式 为__range.begin()
且 尾表达式 为__range.end();
- 否则, 首表达式 为
begin(__range)
1 且 尾表达式 为end(__range)
,通过参数依赖查找寻找(不进行非 ADL 查找)
若 范围表达式 返回临时量,则其生存期被延续到循环结尾,如同绑定到右值引用__range
所示,但要注意 范围表达式 中任何临时量生存期都不被延长 -
正文
我希望这样子遍历
equal_range()
的结果for(auto& j:mb.equal_range("Hello")){ out<<j.second<<", "; }
注意到
equal_range
的返回值类型为std::pair
也就是说当对其使用 范围for 时,会试图对其调用begin()
和end()
以获取__begin
和__end
来作为循环的控制条件.那么要实现如上方式,应当重载begin和end函数namespace std{ template<typename Key,typename T> std::_Rb_tree_iterator<std::pair<Key,T>>& begin(std::pair< std::_Rb_tree_iterator<std::pair<Key,T>>, std::_Rb_tree_iterator<std::pair<Key,T>> >&i){ return i.first; } template<typename Key,typename T> std::_Rb_tree_iterator<std::pair<Key,T>>& end(std::pair< std::_Rb_tree_iterator<std::pair<Key,T>>, std::_Rb_tree_iterator<std::pair<Key,T>> >&i){ return i.second; } }
搞定
- 编者注:值得一提,此处
begin
应当指std::begin
,后文end
亦同 ↩
- 编者注:值得一提,此处