迭代器:类似指针的对象,可以解引用、自增、比较(!=)等操作。
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.
网友评论