multimap, ++iter后,iter->first 和 iter->second的访问问题 ?

LENOVO_ 2010-04-20 07:46:12

#include <iostream>
#include <map>
#include <string>
using namespace std;

int main()
{
multimap<string,string> mm;
mm.insert(make_pair(string("a"),string("a1")));
mm.insert(make_pair(string("a"),string("a2")));
mm.insert(make_pair(string("a"),string("a3")));

multimap<string,string>::size_type count=mm.count(string("a"));
multimap<string,string>::iterator iter=mm.find(string("a"));
for(multimap<string,string>::size_type i=0;i != count; ++i,++iter)
{
cout<<"iter->first : "<<iter->first<<'\t'<<"iter->second : "<<iter-

>second<<endl;
}
return 0;
}


iter->first : a iter->second : a1
iter->first : a iter->second : a2
iter->first : a iter->second : a3
请按任意键继续. . .


这里的 ++iter 到底是怎么工作的?iter->first 为什么不改变?

我查了一下红黑树的C实现,看到一些数据结构的定义:

typedef int key_t;
typedef int data_t;

typedef enum color_t
{
RED = 0,
BLACK = 1
}color_t;

typedef struct rb_node_t
{
struct rb_node_t *left, *right, *parent;
key_t key;
data_t data;
color_t color;
}rb_node_t;



无论怎么思索,都解释不了 ++iter后,iter->first都没变,难道说:

假如一个多键值映射:

a---- a1
---- a2
---- a3
b----b1
----b2


可以解释为:

a---- a1
a---- a2
a---- a3
b----b1
b----b2


这不是浪费了空间吗?


鼠标光标指向multimap后右键转到声明可以看到:

// TEMPLATE CLASS multimap
template<class _Kty,
class _Ty,
class _Pr = less<_Kty>,
class _Alloc = allocator<pair<const _Kty, _Ty> > >
class multimap
: public _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, true> >
{ // ordered red-black tree of {key, mapped} values, non-unique keys
public:
...
};

但我观察只是在

// TEMPLATE CLASS _Tmap_traits
template<class _Kty, // key type
class _Ty, // mapped type
class _Pr, // comparator predicate type
class _Alloc, // actual allocator type (should be value allocator)
bool _Mfl> // true if multiple equivalent keys are permitted
class _Tmap_traits
: public _CONTAINER_BASE_AUX_ALLOC<_Alloc>
{ // traits required to make _Tree behave like a map
public:
...
};

有个

protected:
key_compare comp;

_Pr comp; // the comparator predicate for keys


hehe,呵呵,说了这么多,两句话:
_____________________________
iter到底指向了什么?
为什么++iter后,iter->first都没变
_____________________________
...全文
1164 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
LENOVO_ 2010-04-21
  • 打赏
  • 举报
回复
单步跟踪了一下,在“自动窗口”中看到一些东西:

- mm [3](("a","a1"),("a","a2"),("a","a3"))
+ [0] ("a","a1") std::pair<>
+ [1] ("a","a2") std::pair<>
+ [2] ("a","a3") std::pair<>

"tajon1226"发的那些东西应该也是在这个窗口找到的吧?

假如要我设计multimap我会把key 对应的 mapped_value 设计为一个链表.
然后遍历的话很简单的,

找到 key 对应的 mapped_value 的头结点,然后

mapped_value *p=头结点->next;
while(p != NULL)
{
打印结点;
p=p->next;
}

不管怎么看 iter指向的一定是一个 pair 类型的。

暂且可以这么认为:

a___<a,a1>
|___<a,a2>
|___<a,a3>


有兴趣的可以讨论一下,多映射在数据库中是很常用的数据结构。
cattycat 2010-04-20
  • 打赏
  • 举报
回复
iter->first 输出的是键值,因为你查找键值"a"的,返回的是key是a的开始处迭代器,连续输出的3个都是键值a的。可以看stl的源码解析的书,了解底层实现机制。
走好每一步 2010-04-20
  • 打赏
  • 举报
回复
为键开辟空间了...
不同的a1、a2确实是用红黑树关联起来的。
走好每一步 2010-04-20
  • 打赏
  • 举报
回复
我也有你这个猜测,但觉得 mlutimap 不可能为了照顾 iterator 而额外增加存储空间。
毕竟有一个键就可以了。


...
0x00396574 01 00 cd cd fd fd fd fd ab ab ab ab ab ab ab ab ee fe ee fe 00 00 00 00 00 00 00 00 12 00 12 00 3d 07 1c 00 08 65 39 00 28 66 39 00 00 00 00 00 00 00 00 00 ................................=....e9.(f9.........
0x003965A8 50 00 00 00 01 00 00 00 79 00 00 00 fd fd fd fd 08 64 39 00 28 65 39 00 d8 66 39 00 00 00 00 00 cd cd cd cd 61 61 61 61 61 00 cd cd cd cd cd cd cd cd cd cd P.......y........d9.(e9..f9.........aaaaa...........
0x003965DC 05 00 00 00 0f 00 00 00 00 00 00 00 cd cd cd cd 61 61 61 61 61 31 00 cd cd cd cd cd cd cd cd cd 06 00 00 00 0f 00 00 00 01 00 cd cd fd fd fd fd ab ab ab ab ................aaaaa1..............................
0x00396610 ab ab ab ab ee fe ee fe 00 00 00 00 00 00 00 00 12 00 12 00 4b 07 1c 00 98 65 39 00 b8 66 39 00 00 00 00 00 00 00 00 00 50 00 00 00 01 00 00 00 7a 00 00 00 ....................K....e9..f9.........P.......z...
0x00396644 fd fd fd fd 08 64 39 00 98 64 39 00 08 64 39 00 00 00 00 00 cd cd cd cd 62 62 62 62 62 00 cd cd cd cd cd cd cd cd cd cd 05 00 00 00 0f 00 00 00 00 00 00 00 .....d9..d9..d9.........bbbbb.......................
0x00396678 cd cd cd cd 62 62 62 62 32 00 cd cd cd cd cd cd cd cd cd cd 05 00 00 00 0f 00 00 00 00 00 cd cd fd fd fd fd ab ab ab ab ab ab ab ab ee fe ee fe 00 00 00 00 ....bbbb2...........................................
0x003966AC 00 00 00 00 12 00 12 00 59 07 1c 00 28 66 39 00 00 00 00 00 00 00 00 00 00 00 00 00 50 00 00 00 01 00 00 00 7b 00 00 00 fd fd fd fd 08 64 39 00 b8 65 39 00 ........Y...(f9.............P.......{........d9..e9.
0x003966E0 08 64 39 00 00 00 00 00 cd cd cd cd 61 61 61 61 61 00 cd cd cd cd cd cd cd cd cd cd 05 00 00 00 0f 00 00 00 00 00 00 00 cd cd cd cd 61 61 61 32 00 cd cd cd .d9.........aaaaa...........................aaa2.

走好每一步 2010-04-20
  • 打赏
  • 举报
回复
_Pairib insert(const value_type& _Val)
{ // try to insert node with value _Val
_Nodeptr _Trynode = _Root();
_Nodeptr _Wherenode = _Myhead;
bool _Addleft = true; // add to left of head if tree empty
while (!_Isnil(_Trynode))
{ // look for leaf to insert before (_Addleft) or after
_Wherenode = _Trynode;
_Addleft = _DEBUG_LT_PRED(this->comp,
this->_Kfn(_Val), _Key(_Trynode));
_Trynode = _Addleft ? _Left(_Trynode) : _Right(_Trynode);
}

if (this->_Multi)
return (_Pairib(_Insert(_Addleft, _Wherenode, _Val), true));
else
{ // insert only if unique
iterator _Where = _TREE_ITERATOR(_Wherenode);
if (!_Addleft)
; // need to test if insert after is okay
else if (_Where == begin())
return (_Pairib(_Insert(true, _Wherenode, _Val), true));
else
--_Where; // need to test if insert before is okay

if (_DEBUG_LT_PRED(this->comp,
_Key(_Where._Mynode()), this->_Kfn(_Val)))
return (_Pairib(_Insert(_Addleft, _Wherenode, _Val), true));
else
return (_Pairib(_Where, false));
}
}
na2650945 2010-04-20
  • 打赏
  • 举报
回复
不懂。
帮顶。
等高手解答。
LENOVO_ 2010-04-20
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 selooloo 的回复:]
这里的++和->是重载的,LZ的问题只能查看下源码才能知道
猜测键值相同的又组成一个树
[/Quote]

我也有你这个猜测,但觉得 mlutimap 不可能为了照顾 iterator 而额外增加存储空间。
毕竟有一个键就可以了。

[Quote=引用 2 楼 hairetz 的回复:]


你告诉我,这3个iter->first应该是什么?跟multimap怎么实现有关系么?
[/Quote]

我正是不知道 iter 到底指向了什么所以才问的,我惊叹 ++iter ,cout<<iter->second;的写法!!!

[Quote=引用 3 楼 lcl_data 的回复:]
你的mm里

first都是a啊,……
[/Quote]

呵呵,这个个人觉得是个无用的做法。键不同时肯定会插入的。
十八道胡同 2010-04-20
  • 打赏
  • 举报
回复
你的mm里
multimap<string,string> mm;
mm.insert(make_pair(string("a"),string("a1")));
mm.insert(make_pair(string("a"),string("a2")));
mm.insert(make_pair(string("a"),string("a3")));
first都是a啊,本来就不应该变,你要测试的话,可以改成
multimap<string,string> mm;
mm.insert(make_pair(string("a1"),string("a1")));
mm.insert(make_pair(string("a1"),string("a2")));
mm.insert(make_pair(string("a1"),string("a3")));
至少这样可以看出变化
  • 打赏
  • 举报
回复
iter->first : a iter->second : a1
iter->first : a iter->second : a2
iter->first : a iter->second : a3


你告诉我,这3个iter->first应该是什么?跟multimap怎么实现有关系么?
selooloo 2010-04-20
  • 打赏
  • 举报
回复
这里的++和->是重载的,LZ的问题只能查看下源码才能知道
猜测键值相同的又组成一个树

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧