• C++11 move_iterator


        template<typename Iterator> class move_iterator
        {
            Iterator current;
        public:
            typedef Iterator iterator_type;
            typedef typename std::iterator_traits<Iterator>::iterator_category iterator_category;
            typedef typename std::iterator_traits<Iterator>::value_type value_type;
            typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
            typedef Iterator pointer;
    
            typedef value_type&& reference;
    
            move_iterator(){}
            explicit move_iterator(Iterator it):current(it){}
            template<typename Iter> move_iterator(const move_iterator<Iter>& it):current(it.current){}
            template<typename Iter> move_iterator& operator=(const move_iterator<Iter>&it)
            {
                current = it.current;
            }
            iterator_type  base() const{ return  current;}
            pointer operator->()const{return current;}
    
            reference operator*()const{return std::move(*current);}
    
            move_iterator&operator++(){++current; return *this;}
            move_iterator&operator--(){--current; return *this;}
    
            move_iterator&operator++(int){move_iterator temp = *this; ++current; return temp;}
            move_iterator&operator--(int){move_iterator temp = *this; --current; return temp;}
    
            move_iterator operator+(difference_type n) const {return move_iterator(current + n);}
            move_iterator operator-(difference_type n) const {return move_iterator(current - n);}
            move_iterator operator+=(difference_type n) {current += n; return *this;}
            move_iterator operator-=(difference_type n) {current -= n; return *this;}
    
            auto operator[](difference_type n) const -> decltype(std::move(current[n]))
            {
                return std::move(current[n]);
            }
    
        };
    

     从实现上可以看出,基本是普通Iterator加了外包装。

    其中特别值得注意的几个点:

    typedef value_type&& reference;
    
    auto operator[](difference_type n) const -> decltype(std::move(current[n]))
     {
         return std::move(current[n]);
     }
    
     reference operator*()const{return std::move(*current);}

    可以发现,这种迭代器呈现出差别就在解引用的时候强制转换成右值引用,这样就可以实现从一个容器中”移走“所有的元素

    
    
    #include<vector>
    #include<algorithm>
    #include<stack>
    #include<iostream>
    #include<string>
    using namespace std;
    
    
    int main()
    {
        std::vector<std::string> foo(3);
        std::vector<std::string> bar{"one", "two", "three"};
    
        typedef std::vector<std::string>::iterator Iter;
    
        std::copy(std::move_iterator<Iter>(bar.begin()),
                  std::move_iterator<Iter>(bar.end()), foo.begin());
    
        bar.clear();
        std::cout << "foo:";
        for(std::string& x : foo) cout << ' ' << x;
        std::cout << '
    ';
        return 0;
    }

    对于这个程序,可以跟踪一下,发现最后bar在copy之后,虽然仍旧含有三个元素,但都变成了"",可见已经被“掏空”了

    后面那个clear只是使得bar的size减到0而已,可谓多此一举。

    所有的差别,不过是因为我们输入参数用move_iterator裹了一层:std::move_iterator<Iter>(bar.begin())

    还有就是move_iterator是模板类,不是模板函数,所以需要显式写出模板参数,在这里就显得有些啰嗦了。

    还可以看一下另一个关于解引用的例子

    #include<iterator>
    #include<string>
    #include<iostream>
    #include<vector>
    using namespace std;
    int main()
    {
        std::string str[] = {"one", "two", "three"};
        std::vector<std::string> foo;
    
        std::move_iterator<std::string*> it(str);
        for(int i = 0; i < 3; i++)
        {
            foo.push_back(*it);
            ++it;
        }
        std::cout << "foo:";
        for(std::string& x : foo) std::cout << " " << x;
        std::cout << "
    ";
        return 0;
    }

    因为普通指针也可以被iterator_traits识别为迭代器,所以也可以用move_iterator进行包装

  • 相关阅读:
    判断一下是星期几
    猴子分桃
    免子生免子
    字符串排序
    非关系型数据库(一)
    学习redis简介(一)
    SAVEPOINT
    *****POSTGRESQL文檔
    程序员人生之路(分析的非常透彻!)
    UpperCase for ALL Text Editors
  • 原文地址:https://www.cnblogs.com/hustxujinkang/p/5030760.html
Copyright © 2020-2023  润新知