STL 迭代器(一) 迭代器操作详解


文章目录

      • 前言
      • 一.Functions(函数)操作
      • 二.Iterator generators
      • 三.predefined iterator
        • 1.insert_iterator、back_insert_iterator、front_insert_iterator
        • 2.reverse_iterator
        • 3.istream_iterator ostream_iterator
        • 4.std::move 与 std::move_iterator

前言

首先我们知道在容器中,迭代器分为:

  • iterator
  • const_iterator
  • reverse_iterator
  • const_reverse_iterator

官方文档对迭代器实际上可以分为这几类:

  • Input iterator 输入迭代器
  • Output iterator 输出迭代器
  • Forward iterator 正向迭代器
  • Bidirectional iterator 双向迭代器
  • Random-access iterator 随机存取迭代器

注意每个容器的迭代器类型不一定相同,如vector的迭代器就是随机存取迭代器,而list则是双向迭代器
具体的可以在www.cplusplus.com/reference/iterator/index.html
进行查阅


一.Functions(函数)操作

  • advance
  • distance
  • prev
  • next
void test1()
{
    //advance
    list<int> mylist{1, 2, 3, 4, 5, 6};
    list<int>::iterator it = mylist.begin();
    //it +=5;//ERROR!iterator do not support operator +=
    it++;
    it++;
    it++;
    it++;
    cout << *it << endl;
    it = mylist.begin();
    advance(it, 2);
    cout << *it << endl;

    //distance
    cout << "distance:" << distance(mylist.begin(), it) << endl;

    //prev
    it = mylist.end();
    cout << "The last element:" << *(--it) << endl;
    cout << "Now *it = " << *it << endl;
    cout << "如果并不想要迭代器变化,只想输出迭代器指向前一个元素的迭代器:" << endl;
    cout << *prev(mylist.end()) << endl;
    //next
    cout << *next(mylist.begin()) << endl;

    cout << "next还可以有类似advance的用法,但是也并不会改变原来的迭代器指向" << endl;
    cout << *next(mylist.begin(), 3) << endl;

    cout << "for_each + next" << endl;
    for_each(mylist.begin(), next(mylist.begin(), 3), [](int x) { cout << x << endl; });
}

二.Iterator generators

  • back_inserter:不断往后插入元素
  • front_inserter:不断往前插入元素
  • inserter:需要确定容器与插入的位置

这些操作可以用来针对哪些没有insert函数的容器使用

//例题:要在一个容器中间插入另外一个容器的元素
void test2()
{
    list<int> mylist{1, 2, 3, 4, 5};
    list<int> newlist{10, 20, 30, 40};
    auto it = newlist.begin();
    std::advance(it, 2);
    std::copy(mylist.begin(), mylist.end(), inserter(newlist, it));

    for (auto &e : newlist)
        cout << e << endl;
}

//back_inserter front_inserter
void test3()
{
    list<int> mylist{1, 2, 3, 4, 5};
    list<int> newlist;
    //不要用.end()来执行copy操作,因为.end()返回的并不属于插入迭代器,并不能对newlist进行扩容,所以会发生错误
    // std::copy(mylist.begin(), mylist.end(), newlist.end());

    //back_inserter
    std::copy(mylist.begin(), mylist.end(), std::back_inserter(newlist));

    for (auto &e : newlist)
        cout << e << endl;
    cout << "-----------------------------" << endl;

    //front_inserter 注意这里插入的顺序是相反的
    list<int> mylist2{6, 7, 8, 9};
    std::copy(mylist.begin(), mylist.end(), std::front_inserter(mylist2));

    for (auto &e : mylist2)
        cout << e << endl;
}

三.predefined iterator

1.insert_iterator、back_insert_iterator、front_insert_iterator

  • insert_iterator:容器中必须有insert操作
  • back_insert_iterator:容器中必须有push_back操作
  • front_insert_iterator:容器中必须有push_front操作
void test4()
{
    list<int> mylist{1, 2, 3, 4, 5};
    list<int> newlist;

    //insert_iterator
    std::insert_iterator<list<int>> insert_it(newlist, newlist.begin());
    std::copy(mylist.begin(), mylist.end(), insert_it);

    for (auto &e : newlist)
        cout << e << endl;
    cout << "--------------------------" << endl;

    vector<int> vec{1, 2, 3};
    vector<int> newvec{10, 20, 30};
    std::back_insert_iterator<vector<int>> back_it(newvec);
    std::copy(vec.begin(), vec.end(), back_it); //如果换成vec.end()会报错
    for (auto &e : newvec)
        cout << e << endl;
    cout << "----------------------------------" << endl;

    /*
    //ERROR!vector中没有push_front操作 
    std::front_insert_iterator> front_it(newvec);
    std::copy(vec.begin(), vec.end(), front_it);
    for (auto& e: newvec)
        cout << e << endl;
    */
}

2.reverse_iterator

这里需要特别注意的是:reverse_iterator 相比 iterator 会向左边有1个单位的offset(偏移)

因为STL容器中的函数,如erase, insert函数等等只能操作正向迭代器,不能操作反向迭代器,所以反向迭代器中便有了base函数将其转换为正向迭代器,但是注意有偏移

注意:使用base函数之后,指针右移一位,再转换为正向迭代器

/*
?      1       2       3       4       5       ?
    vec.begin()                              vec.end()
                                      rbeg
rend



*/

void test5()
{
    vector<int> vec{1, 2, 3, 4, 5};

    std::reverse_iterator<vector<int>::iterator> rbeg(vec.end());
    std::reverse_iterator<vector<int>::iterator> rend(vec.begin());

    cout << *rbeg << endl;
    cout << *rbeg.base() << endl;
    cout << *rend << endl;
    cout << *rend.base() << endl;
    cout << "-------用逆向迭代器删除数组中的3------------" << endl;
    std::reverse_iterator<vector<int>::iterator> rit = find(vec.rbegin(), vec.rend(), 3);
    std::reverse_iterator<vector<int>::iterator> rit2 = rit;
    cout << *rit << endl;
    rit++;
    cout << *rit << endl;
    rit++;
    cout << *rit << endl;
    cout << "由此可见rit 的本质仍然是反向迭代器" << endl;
    // vec.erase(rit2);
    // vec.erase(rit2.base());
    vec.erase((++rit2).base());
    cout << "----------------print---------------------------" << endl;
    for (auto &e : vec)
        cout << e << endl;
}

void test6()
{
    vector<int> vec{1, 2, 3, 4, 5};
    std::reverse_iterator<vector<int>::iterator> rbeg(vec.end());
    std::reverse_iterator<vector<int>::iterator> rend(vec.begin());
    cout << "迭代器的类型-----------------------------" << endl;
    vector<int>::reverse_iterator rit = rbeg;
    std::reverse_iterator<vector<int>::iterator> rit2 = rbeg;
    cout << *rit << endl;
    cout << *rit2 << endl;
    cout << "正序打印---------------------------------" << endl;
    for (vector<int>::iterator it = rend.base(); it != rbeg.base(); it++)
        cout << *it << endl;
    cout << "逆序打印---------------------------------" << endl;
    while (rbeg != rend)
        cout << *rbeg++ << endl;
}

3.istream_iterator ostream_iterator

cin输入的次数取决于istream_it迭代器的移动次数
ostream_it会自动输出移动

void test7()
{
    std::istream_iterator<double> istream_it(std::cin);
    std::istream_iterator<double> eof;
    vector<double> vec;
    vec.push_back(*istream_it);
    istream_it++;
    vec.push_back(*istream_it);
    istream_it++;
    vec.push_back(*istream_it);
    istream_it++;

    for (auto &e : vec)
        cout << e << endl;
}

void test8(){
    vector<int> vec{1,2,3,4,5};
    std::ostream_iterator<int> ostream_it(cout," ");
    *ostream_it = 1;
    *ostream_it = 2;
    *ostream_it = 3;
    cout << endl;
    cout << "----------------------------" << endl;
    std::copy(vec.begin(), vec.end(), ostream_it);
}

4.std::move 与 std::move_iterator

移动语义 move 与 移动迭代器
注意:当src元素中move过去之后就不能再使用了,尽管还能够再次输出,但是程序有安全隐患。

void test9(){
    vector<int> src{1,2,3,4};
    vector<int> dest{5,6,7};
    typedef vector<int>::iterator Iter;//定义底层的基本迭代器
    std::copy(std::move_iterator<Iter>(src.begin()), std::move_iterator<Iter>(src.end()), std::back_inserter(dest));
    // std::move(src.begin(), src.end(), std::back_inserter(dest));
    cout << "src:" << endl;
    for (auto& e: src)
        cout << e << " ";
    cout << endl;
    cout << "dest:" << endl;
    for (auto& e: dest)
        cout << e << " ";
    cout << endl; 
}

你可能感兴趣的:(STL)