1. 程式人生 > >STL原始碼分析之set配接器

STL原始碼分析之set配接器

前言

上面兩節我們分析了RB-tree, 同時我們也知道了rb-tree的插入操作還分為可重複插入和不可重複插入(insert_unique). 本節分析set, 嚴格意義說set就是修改了底層容器介面的, 所以應該是配置器. set就是將RB-tree作為底層容器, 以insert_unique為核心的配接器.

set操作

下面是對set的構造和insert的簡單操作, 這裡重複插入one, 但是重複的資料只能被插入一次, 並且不能被修改.

int main()
{
	set<string> str;
	str.insert("zero");
    
	str.
insert("one"); str.insert("one"); str.insert("two"); str.insert("three"); set<string> str1(str.begin(), str.end()); for(const auto &i : str1) cout << i << " "; // one three two zero cout << endl; cout << *str.begin() << " " << str.count
("one") << " " << *str.find("one") << " " << endl; // one 1 one exit(0); }

set分析

set的主要實現大都是呼叫RB-tree的介面.

set型別定義

這裡的型別的定義要注意一點, 都是const型別, 因為set的主鍵定義後就不能被修改了, 所以這裡都是以const型別.

#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template <class Key, class Compare = less<
Key>, class Alloc = alloc> #else template <class Key, class Compare, class Alloc = alloc> #endif class set { public: // typedefs: typedef Key key_type; typedef Key value_type; typedef Compare key_compare; typedef Compare value_compare; private: // 一RB-tree為介面封裝 typedef rb_tree<key_type, value_type, identity<value_type>, key_compare, Alloc> rep_type; rep_type t; // red-black tree representing set public: // 定義的型別都是const型別, 不能修改 typedef typename rep_type::const_pointer pointer; typedef typename rep_type::const_pointer const_pointer; typedef typename rep_type::const_reference reference; typedef typename rep_type::const_reference const_reference; typedef typename rep_type::const_iterator iterator; typedef typename rep_type::const_iterator const_iterator; typedef typename rep_type::const_reverse_iterator reverse_iterator; typedef typename rep_type::const_reverse_iterator const_reverse_iterator; typedef typename rep_type::size_type size_type; typedef typename rep_type::difference_type difference_type; ... };

建構函式

建構函式構造成員的時候呼叫的是RB-tree的insert_unique

class set {
public:
    ...
  set() : t(Compare()) {}
  explicit set(const Compare& comp) : t(comp) {}	// 不能隱式轉換

    // 接受兩個迭代器
    // 建構函式構造成員的時候呼叫的是RB-tree的insert_unique
  template <class InputIterator>
  set(InputIterator first, InputIterator last)
    : t(Compare()) { t.insert_unique(first, last); }
  template <class InputIterator>
  set(InputIterator first, InputIterator last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }

  set(const value_type* first, const value_type* last) 
    : t(Compare()) { t.insert_unique(first, last); }
  set(const value_type* first, const value_type* last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }

  set(const_iterator first, const_iterator last)
    : t(Compare()) { t.insert_unique(first, last); }
  set(const_iterator first, const_iterator last, const Compare& comp)
    : t(comp) { t.insert_unique(first, last); }
    ...
};

成員屬性獲取

class set {
public:
    ...
    // 所有的操作都是通過呼叫RB-tree獲取的
  key_compare key_comp() const { return t.key_comp(); }
  value_compare value_comp() const { return t.key_comp(); }
  iterator begin() const { return t.begin(); }
  iterator end() const { return t.end(); }
  reverse_iterator rbegin() const { return t.rbegin(); } 
  reverse_iterator rend() const { return t.rend(); }
  bool empty() const { return t.empty(); }
  size_type size() const { return t.size(); }
  size_type max_size() const { return t.max_size(); }
    // 交換
  void swap(set<Key, Compare, Alloc>& x) { t.swap(x.t); }

    // 其他的find, count等都是直接呼叫的RB-tree的介面
  iterator find(const key_type& x) const { return t.find(x); }
  size_type count(const key_type& x) const { return t.count(x); }
  iterator lower_bound(const key_type& x) const {
    return t.lower_bound(x);
  }
  iterator upper_bound(const key_type& x) const {
    return t.upper_bound(x); 
  }
  pair<iterator,iterator> equal_range(const key_type& x) const {
    return t.equal_range(x);
  }
    ...
};
template <class Key, class Compare, class Alloc>
inline void swap(set<Key, Compare, Alloc>& x, set<Key, Compare, Alloc>& y) 
{
  x.swap(y);
}

insert

class set {
public:
    ...
    // pair型別我們準備下一節分析, 這裡是直接呼叫insert_unique, 返回插入成功就是pair( , true), 插入失敗則是( , false)
  typedef  pair<iterator, bool> pair_iterator_bool; 
  pair<iterator,bool> insert(const value_type& x) { 
    pair<typename rep_type::iterator, bool> p = t.insert_unique(x); 
    return pair<iterator, bool>(p.first, p.second);
  }
    // 指定位置的插入
  iterator insert(iterator position, const value_type& x) {
    typedef typename rep_type::iterator rep_iterator;
    return t.insert_unique((rep_iterator&)position, x);
  }
    // 可接受範圍插入
  template <class InputIterator>
  void insert(InputIterator first, InputIterator last) {
    t.insert_unique(first, last);
  }
    ...
};

erase

class set {
public:
    ...
     // erase的實現是通過呼叫RB-tree實現的erase
  void erase(iterator position) { 
    typedef typename rep_type::iterator rep_iterator;
    t.erase((rep_iterator&)position); 
  }
  size_type erase(const key_type& x) { 
    return t.erase(x); 
  }
  void erase(iterator first, iterator last) { 
    typedef typename rep_type::iterator rep_iterator;
    t.erase((rep_iterator&)first, (rep_iterator&)last); 
  }
  void clear() { t.clear(); }
	...
};

過載

過載運算子也是以RB-tree為介面呼叫.

class set {
public:
    ...

  set(const set<Key, Compare, Alloc>& x) : t(x.t) {}
  set<Key, Compare, Alloc>& operator=(const set<Key, Compare, Alloc>& x) { 
    t = x.t; 
    return *this;
  }
    ...
};

template <class Key, class Compare, class Alloc>
inline bool operator==(const set<Key, Compare, Alloc>& x, 
                       const set<Key, Compare, Alloc>& y) {
  return x.t == y.t;
}

template <class Key, class Compare, class Alloc>
inline bool operator<(const set<Key, Compare, Alloc>& x, 
                      const set<Key, Compare, Alloc>& y) {
  return x.t < y.t;
}

總結

本節簡單的分析了set主要是以RB-tree介面實現的配置器, set每個元素被初始化之後就不能進行修改, 這都是set定義型別的時候都是const型別