我们知道STL中我们常用的set
与multiset
和map
与multimap
都是基于红黑树。本文介绍了它们的在STL中的底层数据结构_Rb_tree
的直接用法与部分函数。难点主要是_Rb_tree
的各个参数的确定。
特别注意在如下代码的Selector
类用于从Node
中选出用于排序的key值,这个仿函数必须返回const int&
而不能是int
,否则less<int>::operator(const int&, const int&)
会抛出segmentation fault
。一开始写成int
,看了很多源码才发现是这个原因,一定要注意。(Update on 2020-5-6:通过对源码阅读,终于彻底明白为何出现写int
会出现问题,见文末)
接下来是样例代码,里面都有注释了。
1 |
|
程序的输出为(内存地址不定):
1 | insert address = 0xf91be0 |
Update on 2020-5-6
当将Selector::operator()
的返回值写为int
时,执行时会在main()
中的it = tree.find(1)
时抛出Segmentation Fault
。以下给出调用过程。
1 | // main.cpp, main() |
在此处的 _M_impl._M_key_compare
也就是比较仿函数对象,在这里即less<int>
对象。异常就是在这个函数里抛出的,可见问题出现在 _S_key(__x)
中。
1 | // stl_tree.h, std::_Rb_tree::_S_key(_Const_Base_ptr) |
这里的 _KeyOfValue()
就是我们给的 Selector
了。所以在这里如果将 operator()
的返回值写为 int
,则这里将其以 const _Key&
返回,就是返回局部对象的引用,后面又在 less<int>::operator()
里面使用了这个引用(这个引用实际上指向一个已过期的栈上数据: _KeyOfValue()
的返回值),这个行为导致了Segmentation Fault
。