美文网首页
C++:迭代器的设计与实现

C++:迭代器的设计与实现

作者: 圣地亚哥_SVIP | 来源:发表于2020-06-09 23:01 被阅读0次

迭代器:类似指针的对象,可以解引用、自增、比较(!=)等操作。

STL中,迭代器用来STL Algorithm与Container之间的粘合剂。

迭代器根据移动特性及施行操作,可以分为5类:

  • Input Iterator: 只读
  • Output Iterator: 只写
  • Forward Iterator: 可单向移动,支持读写。支持operator++
  • Bidirectional Iterator: 双向移动,可走访某个容器区间。支持operator++ 和 operator--
  • Random Access Iterator: 可涵盖所有指针算术能力,如数组连续内存空间的定义此类型

定义迭代器内嵌的型别:

  • using value_type = T; /* 迭代器所指对象类型 */
  • using reference = typename std::add_lvalue_reference<T>::type; /* 迭代所指对象引用类型 */
  • using pointer = typename std::add_pointer<T>::type; /* 迭代器所指对象指针类型 */
  • using difference_type = std::ptrdiff_t; /* 表示两个迭代器的距离 */
  • using iterator_category = std::forward_iterator_tag; /* 迭代器的类型 */

针对一个链表结构的容器:

定义两类迭代器: iterator/const iterator,迭代器基本的操作能力:

  • operator ++()
  • operator ++(int)
  • operator !=(para)
  • operator *()
  • operator ==()

针对容器本身,设计方法如下,注意在容器中使用了一个_root来连接链表的头和尾,初始化时,只有一个_root,next/prev指向自己:

  • begin()
  • end()
  • push_back()
  • push_front()
  • pop_back()
  • pop_front()
  • back()
  • insert(iterator pos,val)
  • erase(iterator)

实现代码如下,参考stl_list

#include <iostream>
#include <algorithm>
#include <list>
#include <gtest/gtest.h>
#include <string>

/*
** 定义list,Node积累,主要包含前后指针
** 定义两个操作函数:分别是在此节点后插入,其次是将本身从list链表中移除
*/
struct list_base{
public:
    list_base* next;
    list_base* prev;
    list_base(){
        next = this;
        prev = this;
    }
    virtual void insert(list_base* e){
        e->next = this;
        e->prev = prev;
        prev->next = e;
        prev = e;
    }
    virtual void unlink(){
        next->prev = prev;
        next->prev->next = next;
        next = this;
        prev = this;
    }
    virtual ~list_base(){}
};

/*
** 存放数据
*/
template<typename T>
class Node: public list_base{
public:
    T ele;
public:
    Node(T ele):ele(ele){}
};

/*
** 定义迭代器iterator
*/
template<typename T>
class buffers_iterator{
public:

    list_base* cur;
    using _self = buffers_iterator<T>;
    using _Node = Node<T>;
public:
    
    using value_type = T;
    using reference = std::add_lvalue_reference_t<T>;
    using pointer = std::add_pointer_t<T>;
    using difference_type = std::ptrdiff_t;

    /* 
    * 由于是链表结构,因此只支持std::forward_iterator_tag 
    * 连续容器使用:std::random_access_iterator_tag
    */
    using iterator_category = std::forward_iterator_tag;

    buffers_iterator(list_base* const p)
    : cur(p){
    }
    buffers_iterator()=default;
    template<typename U>
    buffers_iterator(const buffers_iterator<U>& other)
    : cur(other.cur){
    }
    reference operator*(){
        return static_cast<_Node*>(cur)->ele;
    }
    pointer operator->(){
        return &(static_cast<_Node*>(cur)->ele);
    }
    _self& operator++(){
        cur = cur->next;
        return *this;
    }
    _self operator++(int){
        const auto temp(*this);
        ++*this;
        return temp;
    }
    template<typename U>
    _self& operator=(const buffers_iterator<U>& other){
        cur = other.cur;
        return *this;
    }
    bool operator==(const buffers_iterator& other){
        return cur==other.cur;
    }
    bool operator!=(const buffers_iterator& other){
        return !(*this==other);
    }
};

/*
** 定义const iterator
** iterator与const iterator区别:const reference及const pointer,以禁止通过此迭代器对存储的数据进行更改
*/
template<typename T>
class buffers_const_iterator{
public:
    list_base* cur;
    using _self = buffers_const_iterator<T>;
    using _Node = const Node<T>;
public:
    using value_type = T;
    using reference = std::add_lvalue_reference_t<std::add_const_t<T>>;
    using pointer = std::add_pointer_t<std::add_const_t<T>>;
    using difference_type = std::ptrdiff_t;
    /* 
    * 由于是链表结构,因此只支持std::forward_iterator_tag 
    * 连续容器使用:std::random_access_iterator_tag
    */
    using iterator_category = std::forward_iterator_tag;

    using iterator = buffers_iterator<T>;

    buffers_const_iterator(list_base* const p)
    : cur(p){
    }

    buffers_const_iterator(const iterator& p)
    :cur(p.cur){}

    buffers_const_iterator()=default;
    template<typename U>
    buffers_const_iterator(const buffers_const_iterator<U>& other)
    : cur(other.cur){
    }
    reference  operator*(){
        return static_cast<_Node*>(cur)->ele;
    }
    pointer operator->(){
        return &(static_cast<_Node*>(cur)->ele);
    }
    _self& operator++(){
        cur = cur->next;
        return *this;
    }
    _self operator++(int){
        const auto temp(*this);
        ++*this;
        return temp;
    }
    template<typename U>
    _self& operator=(const buffers_const_iterator<U>& other){
        cur = other.cur;
        return *this;
    }
    bool operator==(const buffers_const_iterator& other){
        return cur==other.cur;
    }
    bool operator!=(const buffers_const_iterator& other){
        return !(*this==other);
    }
};

/*
** 定义iterator与const iterator之间的比较函数
*/
template<typename _Val>
inline bool
  operator==(const buffers_iterator<_Val>& __x,
         const buffers_const_iterator<_Val>& __y)
  { return __x.cur == __y.cur; }

template<typename _Val>
  inline bool
  operator!=(const buffers_iterator<_Val>& __x,
         const buffers_const_iterator<_Val>& __y)
  { return __x.cur == __y.cur; }

/*
** 定义list容器,在容器内声明iterator及const iterator两种迭代器类型
** 定义接口函数
*/
template<typename T>
class buffers{
    using _Node = Node<T>;
    list_base _root;
public: 
    using iterator = buffers_iterator<T>;
    using const_iterator = buffers_const_iterator<T>;
    using value_type = T;

    buffers(){
        _root.next = &_root;
        _root.prev = &_root;
    }
    buffers(const buffers&) = delete;
    buffers(buffers&& other){
          _root.next = other._root.next == &other._root ? &_root : other._root.next;
          _root.prev = other._root.prev == &other._root ? &_root : other._root.prev;
          other._root.next = &other._root;
          other._root.prev = &other._root;
    }
    void push_back(value_type val) {
        list_base* item = new _Node(val);
        _root.insert(item);
      }

    void push_front(value_type val) {
        list_base* item = new _Node(val);
        begin().cur->insert(item);
    }
    const_iterator begin() const {
          return const_iterator(_root.next);
    }
    const_iterator end() const {
        return const_iterator(&_root);
    }
    iterator begin() {
        return iterator(_root.next);
    }
    iterator end() {
        return iterator(&_root);
    }

    iterator back() {
        return iterator(_root.prev);
    }

    const_iterator back() const{
        return iterator(_root.prev);
    }

    void pop_back(){
        if ( _root.prev == &_root){
            return;
        }
        _erase(_root.prev);
    }

    void pop_front(){
        if (_root.next == &_root){
            return;
        }
        _erase(_root.next);
    }

    iterator insert(iterator pos,const value_type& _val){
        list_base* item = new _Node(_val);
        pos.cur->insert(item);
        return pos.cur->prev;
    }

    iterator erase(iterator pos){
        iterator tmp = pos++;
        _erase(tmp);
        return pos;
    }

    void _erase(iterator pos){
        pos.cur->unlink();
        delete pos.cur;
    }

    bool empty(){
        return _root.next == &_root;
    }

    ~buffers(){
        list_base* head = _root.next;
        list_base* t = _root.next;
        while (head!=&_root){
            head = t->next;
            delete t;
            t = head;
        }
    }
};


TEST(INT,PUSH){
    buffers<int> t1;
    t1.push_back(1);
    EXPECT_EQ(*(t1.back()),1);
    t1.push_front(2);
    EXPECT_EQ(*(t1.begin()),2);
}
TEST(INT,POP){
    buffers<int> t1;
    t1.push_back(2);
    t1.pop_back();
    EXPECT_TRUE(t1.empty());
}
TEST(INT,ITERATOR){
    buffers<int> t1;
    t1.push_front(1);
    t1.insert(t1.begin(),2);
    EXPECT_EQ(*(t1.begin()),2);
    t1.erase(t1.begin());
    EXPECT_EQ(*(t1.begin()),1);
}

/*
** Test String
*/

TEST(STRING,PUSH){
    buffers<std::string> t1;
    t1.push_back("abc");
    EXPECT_EQ(*(t1.back()),"abc");
    t1.push_front("dc");
    EXPECT_EQ(*(t1.begin()),"dc");
}
TEST(STRING,POP){
    buffers<std::string> t1;
    t1.push_back("dc");
    t1.pop_back();
    EXPECT_TRUE(t1.empty());
}
TEST(STRING,ITERATOR){
    buffers<std::string> t1;
    t1.push_front("as");
    t1.insert(t1.begin(),"dc");
    EXPECT_EQ(*(t1.begin()),"dc");
    t1.erase(t1.begin());
    EXPECT_EQ(*(t1.begin()),"as");
}

TEST(ALGORITHM,FIND_IF){
    buffers<int> t1;
    t1.push_back(12);
    t1.push_back(10);
    t1.push_back(5);
    t1.push_back(20);
    auto it = std::find_if(t1.begin(),t1.end(),[](auto e){return e%5==0;});
    EXPECT_EQ(*it,10);
}

int main(int argc,char* argv[]){

    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
    
}

利用gtest单元测试:

# g++ --std=c++1y -g test_iter.cc -o test_iter -lgtest
# ./test_iter 
[==========] Running 7 tests from 3 test cases.
[----------] Global test environment set-up.
[----------] 3 tests from INT
[ RUN      ] INT.PUSH
[       OK ] INT.PUSH (0 ms)
[ RUN      ] INT.POP
[       OK ] INT.POP (0 ms)
[ RUN      ] INT.ITERATOR
[       OK ] INT.ITERATOR (0 ms)
[----------] 3 tests from INT (0 ms total)

[----------] 3 tests from STRING
[ RUN      ] STRING.PUSH
[       OK ] STRING.PUSH (0 ms)
[ RUN      ] STRING.POP
[       OK ] STRING.POP (0 ms)
[ RUN      ] STRING.ITERATOR
[       OK ] STRING.ITERATOR (0 ms)
[----------] 3 tests from STRING (1 ms total)

[----------] 1 test from ALGORITHM
[ RUN      ] ALGORITHM.FIND_IF
[       OK ] ALGORITHM.FIND_IF (0 ms)
[----------] 1 test from ALGORITHM (0 ms total)

[----------] Global test environment tear-down
[==========] 7 tests from 3 test cases ran. (1 ms total)
[  PASSED  ] 7 tests.

相关文章

网友评论

      本文标题:C++:迭代器的设计与实现

      本文链接:https://www.haomeiwen.com/subject/oesytktx.html