C++ 11 set 插入元素 维护唯一性原理

环境:gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) 

std::set 的底层红黑树在插入元素时需要​​频繁调用比较函数​​来维护有序性和唯一性

源码:

//位置 /usr/include/c++/11/bits/stl_tree.h

//插入逻辑
    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
#if __cplusplus >= 201103L
    _M_insert_unique(_Arg&& __v)
#else
    _M_insert_unique(const _Val& __v)
#endif
    {
      typedef pair _Res;
//查找插入位置 触发多次比较
      pair<_Base_ptr, _Base_ptr> __res
    = _M_get_insert_unique_pos(_KeyOfValue()(__v));

      if (__res.second)//允许插入
    {
      _Alloc_node __an(*this);
      return _Res(_M_insert_(__res.first, __res.second,
                 _GLIBCXX_FORWARD(_Arg, __v), __an),
              true);
    }

      return _Res(iterator(__res.first), false);//重复
    }

//查找位置
    _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
    _M_get_insert_unique_pos(const key_type& __k)
    {
      typedef pair<_Base_ptr, _Base_ptr> _Res;
      _Link_type __x = _M_begin();//从根节点开始
      _Base_ptr __y = _M_end();
      bool __comp = true;
      while (__x != 0)//遍历树
    {
      __y = __x;
      __comp = _M_impl._M_key_compare(__k, _S_key(__x));//调用operator<
      __x = __comp ? _S_left(__x) : _S_right(__x);//选择子树
    }
      iterator __j = iterator(__y);
      if (__comp)
    {
      if (__j == begin())
        return _Res(__x, __y);
      else
        --__j;
    }
//唯一性检查
      if (_M_impl._M_key_compare(_S_key(__j._M_node), __k))
    return _Res(__x, __y);
      return _Res(__j._M_node, 0);
    }

测试代码:

#include 
#include 

using namespace std;
class Example {
private:
    int x;

public:
    Example(int a) : x(a) {}
    void print() const { cout << x << " "; }

    bool operator<(const Example& ex) const {
        cout << "< compare" << endl;
        return x < ex.x;
    }
};

void display(set& st) {
    for (auto& n : st) {
        n.print();
    }
    cout << endl;
}

void test() {
    set st = {{2}, {3}, {4}, {2}, {5}, {3}};
    display(st);
}

int main(int argc, char* argv[]) {
    test();
    return 0;
}

运行结果:

C++ 11 set 插入元素 维护唯一性原理_第1张图片

你可能感兴趣的:(笔记,c++,set)