看一下bits/stl_map和bits/stl_set能够看到map和set的定义例如以下:
84 template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>, 85 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > 86 class map 87 { 88 public: 89 typedef _Key key_type; 90 typedef _Tp mapped_type; 91 typedef std::pair<const _Key, _Tp> value_type; 92 typedef _Compare key_compare; 93 typedef _Alloc allocator_type; 94 95 private: 96 // concept requirements 97 typedef typename _Alloc::value_type _Alloc_value_type; 98 __glibcxx_class_requires(_Tp, _SGIAssignableConcept) 99 __glibcxx_class_requires4(_Compare, bool, _Key, _Key, 100 _BinaryFunctionConcept) 101 __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) 102 103 public: 104 class value_compare 105 : public std::binary_function<value_type, value_type, bool> 106 { 107 friend class map<_Key, _Tp, _Compare, _Alloc>; 108 protected: 109 _Compare comp; 110 111 value_compare(_Compare __c) 112 : comp(__c) { } 113 114 public: 115 bool operator()(const value_type& __x, const value_type& __y) const 116 { return comp(__x.first, __y.first); } 117 }; 118 119 private: 120 /// This turns a red-black tree into a [multi]map. 121 typedef typename _Alloc::template rebind<value_type>::other 122 _Pair_alloc_type; 123 124 typedef _Rb_tree<key_type, value_type, _Select1st<value_type>, 125 key_compare, _Pair_alloc_type> _Rep_type; 126 127 /// The actual tree structure. 128 _Rep_type _M_t;
85 template<typename _Key, typename _Compare = std::less<_Key>, 86 typename _Alloc = std::allocator<_Key> > 87 class set 88 { 89 // concept requirements 90 typedef typename _Alloc::value_type _Alloc_value_type; 91 __glibcxx_class_requires(_Key, _SGIAssignableConcept) 92 __glibcxx_class_requires4(_Compare, bool, _Key, _Key, 93 _BinaryFunctionConcept) 94 __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) 95 96 public: 97 // typedefs: 98 //@{ 99 /// Public typedefs. 100 typedef _Key key_type; 101 typedef _Key value_type; 102 typedef _Compare key_compare; 103 typedef _Compare value_compare; 104 typedef _Alloc allocator_type; 105 //@} 106 107 private: 108 typedef typename _Alloc::template rebind<_Key>::other _Key_alloc_type; 109 110 typedef _Rb_tree<key_type, value_type, _Identity<value_type>, 111 key_compare, _Key_alloc_type> _Rep_type; 112 _Rep_type _M_t; // Red-black tree representing set. 113
因为map,set的本身定义都是声明不论什么成员变量,全部成员变量都是从_Rb_tree继承过来的,唯一的区别仅仅是_Rb_tree最后參数的定义不一样.
set的特征例如以下:
1. set对象有五个成员_M_node_count标明map有多少个元素,三个指针分别指向树中最左的节点,树的根节点,树的最右节点,_M_color表明是红树还是黑树。_M_key_compare指向比較函数
2. 树的根节点的_M_parent指向头节点
3. 每个节点的值都紧跟着_M_right
看一下样例:
1 #include <set> 2 3 int main() 4 { 5 std::set<int> iSet; 6 iSet.insert( 0x523 ); 7 iSet.insert( 0x352 ); 8 iSet.insert( 0x808 ); 9 10 return 0; 11 }
看一下main函数的汇编:
(gdb) disassemble main Dump of assembler code for function main: 0x08048634 <+0>: lea 0x4(%esp),%ecx 0x08048638 <+4>: and $0xfffffff0,%esp 0x0804863b <+7>: pushl -0x4(%ecx) 0x0804863e <+10>: push %ebp 0x0804863f <+11>: mov %esp,%ebp 0x08048641 <+13>: push %esi 0x08048642 <+14>: push %ebx 0x08048643 <+15>: push %ecx 0x08048644 <+16>: sub $0x5c,%esp 0x08048647 <+19>: lea -0x54(%ebp),%eax 0x0804864a <+22>: mov %eax,(%esp) 0x0804864d <+25>: call 0x8048712 <_ZNSt3setIiSt4lessIiESaIiEEC2Ev> 0x08048652 <+30>: movl $0x523,-0x34(%ebp) 0x08048659 <+37>: lea -0x3c(%ebp),%eax 0x0804865c <+40>: lea -0x34(%ebp),%edx 0x0804865f <+43>: mov %edx,0x8(%esp) 0x08048663 <+47>: lea -0x54(%ebp),%edx 0x08048666 <+50>: mov %edx,0x4(%esp) 0x0804866a <+54>: mov %eax,(%esp) 0x0804866d <+57>: call 0x804878c <_ZNSt3setIiSt4lessIiESaIiEE6insertERKi> 0x08048672 <+62>: sub $0x4,%esp 0x08048675 <+65>: movl $0x352,-0x28(%ebp) 0x0804867c <+72>: lea -0x30(%ebp),%eax ---Type <return> to continue, or q <return> to quit--- 0x0804867f <+75>: lea -0x28(%ebp),%edx 0x08048682 <+78>: mov %edx,0x8(%esp) 0x08048686 <+82>: lea -0x54(%ebp),%edx 0x08048689 <+85>: mov %edx,0x4(%esp) 0x0804868d <+89>: mov %eax,(%esp) 0x08048690 <+92>: call 0x804878c <_ZNSt3setIiSt4lessIiESaIiEE6insertERKi> 0x08048695 <+97>: sub $0x4,%esp 0x08048698 <+100>: movl $0x808,-0x1c(%ebp) 0x0804869f <+107>: lea -0x24(%ebp),%eax 0x080486a2 <+110>: lea -0x1c(%ebp),%edx 0x080486a5 <+113>: mov %edx,0x8(%esp) 0x080486a9 <+117>: lea -0x54(%ebp),%edx 0x080486ac <+120>: mov %edx,0x4(%esp) 0x080486b0 <+124>: mov %eax,(%esp) 0x080486b3 <+127>: call 0x804878c <_ZNSt3setIiSt4lessIiESaIiEE6insertERKi> 0x080486b8 <+132>: sub $0x4,%esp 0x080486bb <+135>: mov $0x0,%ebx 0x080486c0 <+140>: lea -0x54(%ebp),%eax 0x080486c3 <+143>: mov %eax,(%esp) 0x080486c6 <+146>: call 0x80486fe <_ZNSt3setIiSt4lessIiESaIiEED2Ev> 0x080486cb <+151>: mov %ebx,%eax 0x080486cd <+153>: lea -0xc(%ebp),%esp 0x080486d0 <+156>: add $0x0,%esp ---Type <return> to continue, or q <return> to quit--- 0x080486d3 <+159>: pop %ecx 0x080486d4 <+160>: pop %ebx 0x080486d5 <+161>: pop %esi 0x080486d6 <+162>: pop %ebp 0x080486d7 <+163>: lea -0x4(%ecx),%esp 0x080486da <+166>: ret 0x080486db <+167>: mov %edx,%ebx 0x080486dd <+169>: mov %eax,%esi 0x080486df <+171>: lea -0x54(%ebp),%eax 0x080486e2 <+174>: mov %eax,(%esp) 0x080486e5 <+177>: call 0x80486fe <_ZNSt3setIiSt4lessIiESaIiEED2Ev> 0x080486ea <+182>: mov %esi,%eax 0x080486ec <+184>: mov %ebx,%edx 0x080486ee <+186>: mov %eax,(%esp) 0x080486f1 <+189>: call 0x8048564 <_Unwind_Resume@plt> End of assembler dump.
由上面汇编可知,ebp-0x54是set的this指针.
在0x080486b8指令地址打断点,验证一下set的特征是不是对的.
(gdb) x /8wx $ebp-0x54 0xbffff234: 0xbffff270 0x00000000 0x0804b008 0x0804b020 0xbffff244: 0x0804b038 0x00000003 0x0804b008 0xbffff201 (gdb) x /8wx 0x0804b008 0x804b008: 0x00000001 0xbffff238 0x0804b020 0x0804b038 0x804b018: 0x00000523 0x00000019 0x00000000 0x0804b008 (gdb) x /8x 0x0804b020 0x804b020: 0x00000000 0x0804b008 0x00000000 0x00000000 0x804b030: 0x00000352 0x00000019 0x00000000 0x0804b008 (gdb) x /8wx 0x0804b038 0x804b038: 0x00000000 0x0804b008 0x00000000 0x00000000 0x804b048: 0x00000808 0x00020fb9 0x00000000 0x00000000
可用下图表示:
可知,特征是没有问题