1. 程式人生 > >[C/C++]_[初級]_[關於OutputIterator的簡單介紹]

[C/C++]_[初級]_[關於OutputIterator的簡單介紹]

場景

1.我們在使用演算法庫時, 免不了需要對集合進行排序, 複製, 移動等, 而對集合的元素進行操作就需要用到列舉(itereator).

2.我們一般是對已存在的集合進行遍歷, 刪除, 但是如果需要複製一個集合A內的元素到一個集合B內時如何操作, 這時候列舉怎麼使用? 用列舉能很方便進行多元素新增, 而不需要使用效率低下的 for 迴圈.

說明

1.Iterator可以理解為一種可以對集合的元素進行標識和來回移動的型別, 也可以理解為一個抽象的指標. 它包括5 種類型的列舉: InputIterator, OutputIterator, ForwardIterator, BidirectionalIterator, 和 RandomAccessIterator

; 如果是C++17 還包含一種型別 ContiguousIterator.

2.OutputIterator 是一種列舉, 它可以寫入指向的元素. ForwardIterator, BidirectionalIterator, 或者 RandomAccessIterator 都是 OutputIterator的一種. OutputIterator 滿足我們最常用的幾種操作:

3.std::back_inserter 能快速的建立一個通過容器push_back函式新增元素的列舉, 當然容器要有push_back函式.

4.std::inserter 能快速的建立一個通過容器的insert函式新增元素的列舉, 當然容器要有insert函式, 沒有編譯報錯.

*r = o // 這個比較特殊, r首先解引用後賦值, 之後r遞增1, 指向下一個元素位置.
++r
r++
*r++ = o

例子

#include <assert.h>
#include <iostream>
#include <utility>
#include <iterator>
#include <set>
#include <typeinfO>

template <class A>
static void PrintArray(A& a)
{
  std::cout << typeid
(a).name() << std::endl; if(a.begin() == a.end()) return; auto ite = a.begin(); std::cout << "("; std::cout << *ite; ite++; for(; ite != a.end();++ite){ std::cout << "," << *ite; } std::cout << ")" << std::endl; } void TestIterator() { std::vector<int> v; // back_insert_iterator 的用法, operator= 插入一個數據, 因為是back列舉, 每次都會呼叫 // container的push_back函式. auto& itev = std::back_inserter(v); itev = 1; itev = 2; itev = 3; itev = 4; itev = 5; itev = 5; PrintArray(v); std::vector<int> f; f.push_back(-1); f.push_back(-2); f.push_back(-3); PrintArray(f); // 複製 v內的陣列到f, 從f的第2個位置開始. std::copy(v.begin(),v.end(),std::inserter(f,std::next(f.begin()))); PrintArray(f); // 複製vector到set, 過濾掉重複的. // std::inserter 每次都會呼叫容器的insert函式. std::set<int> s; std::copy(v.begin(), v.end(),std::inserter(s,s.begin())); PrintArray(s); std::vector<int> result; std::sort(v.begin(),v.end()); std::sort(f.begin(),f.end()); // 獲取兩個集合的差集 // 如果直接使用 result.begin()的話會崩潰, // vector iterator not incrementable; // 因為 result.begin()不是OutputIterator, iterator不可以遞增,result本身沒有元素. //std::set_difference(f.begin(),f.end(),v.begin(),v.end(),result.begin()); std::set_difference(f.begin(),f.end(),v.begin(),v.end(),std::back_inserter(result)); PrintArray(result); }

輸出:

class std::vector<int,class std::allocator<int> >
(1,2,3,4,5,5)
class std::vector<int,class std::allocator<int> >
(-1,-2,-3)
class std::vector<int,class std::allocator<int> >
(-1,1,2,3,4,5,5,-2,-3)
class std::set<int,struct std::less<int>,class std::allocator<int> >
(1,2,3,4,5)
class std::vector<int,class std::allocator<int> >
(-3,-2,-1)

參考

OutputIterator
concept-Iterator
iterator
back_inserter
insert_iterator
inserter
next
copy