C++中istream_iterator和ostream_iterator的用法
阿新 • • 發佈:2018-11-11
寫在前面
今天在看《STL原始碼剖析》的時候,看到了配接器中的ostream iterator,其中包含istream_iterator以及ostream_iterator以及更多,感覺這兩個都十分重要,所以在這裡介紹一下
istream_iterator
原始碼:
template <class T, class Distance = ptrdiff_t> class istream_iterator { friend bool operator== __STL_NULL_TMPL_ARGS (const istream_iterator<T, Distance>& x, const istream_iterator<T, Distance>& y); protected: istream* stream; T value; bool end_marker; //判斷是否讀入結束符,比如C語言中的EOF等等 void read() { //其中呼叫的讀取函式 end_marker = (*stream) ? true : false; if (end_marker) *stream >> value; //讀入value end_marker = (*stream) ? true : false; } public: typedef input_iterator_tag iterator_category; typedef T value_type; typedef Distance difference_type; typedef const T* pointer; typedef const T& reference; istream_iterator() : stream(&cin), end_marker(false) {} //預設建構函式,不會觸發輸入操作 istream_iterator(istream& s) : stream(&s) { read(); } //這種建構函式,後面就緊跟著讀取一個數據 reference operator*() const { return value; } #ifndef __SGI_STL_NO_ARROW_OPERATOR pointer operator->() const { return &(operator*()); } #endif /* __SGI_STL_NO_ARROW_OPERATOR */ istream_iterator<T, Distance>& operator++() { //重點過載operator++ read(); return *this; } istream_iterator<T, Distance> operator++(int) { //將operator++過載為輸入操作 istream_iterator<T, Distance> tmp = *this; read(); return tmp; } };
構造方法:
istream_iterator<int> intie(cin); //後面緊跟要輸入一個數據
istream_iterator<int> intie_(); //預設構造方法
通過上面的原始碼知道,當呼叫istream_iterator物件的operator++操作時,就會被過載為輸入一個物件
ostream_iterator
原始碼:
template <class T> class ostream_iterator { protected: ostream* stream; const char* string; //可以包含第二個引數,輸出對應的資料後,輸出此stream public: typedef output_iterator_tag iterator_category; //迭代器型別 typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference; ostream_iterator(ostream& s) : stream(&s), string(0) {} //預設一個引數的建構函式,預設string為空 ostream_iterator(ostream& s, const char* c) : stream(&s), string(c) {} //包含string的建構函式 ostream_iterator<T>& operator=(const T& value) { //重點!!!過載operator=操作,轉換為輸出此value *stream << value; if (string) *stream << string; return *this; } ostream_iterator<T>& operator*() { return *this; } //都返回本身 ostream_iterator<T>& operator++() { return *this; } ostream_iterator<T>& operator++(int) { return *this; } };
構造方式:
ostream_iterator<int> outie(cout); //string預設為null
ostream_iterator<int> outie_(cout, " !! "); //同時也構造string
通過原始碼看出,當ostream_iterator遇到operator=操作是,會被過載為輸出操作。
具體用法
使用ostream_iterator以及istream_iterator的時候,要確保使用對應的方法,例:
#include <iostream> #include <thread> #include <vector> #include <numeric> #include <algorithm> #include <cstring> #include <deque> #include <iterator> using namespace std; int main() { deque<int> id; istream_iterator<int> intie(cin),eos; //開始觸發一次輸入 copy(intie, eos, inserter(id, id.begin())); //迭代器型別為InputIterator,所以這裡呼叫copy的時候採用*result = *first;版本,會使用過載型別 ,那麼就會轉換為插入操作 //其中++first會繼續呼叫下一個,然後過載為新的輸入 ostream_iterator<int> outie(cout, " "); //deque的迭代器型別為random_access_iterator,也會是 *result = *first;呼叫賦值操作 result++操作,返回本身,不影響後面的輸出操作 copy(id.begin(), id.end(), outie); //將=操作,轉換為輸出操作 cout << endl; system("pause"); }
我們這裡使用的第一個copy方法,裡面採用迴圈賦值的方式進行操作,如下:
template <class InputIterator, class OutputIterator>
inline OutputIterator __copy(InputIterator first, InputIterator last, //迭代器型別為input_iterator
OutputIterator result, input_iterator_tag)
{
for ( ; first != last; ++result, ++first) //直接以迭代器是否相等來進行判斷迴圈是否繼續進行,速度慢
*result = *first;
return result;
}
第二個copy方法,也是採用迴圈賦值的方式操作(因為deque中迭代器的型別為:random_access_iterator_tag):
template <class RandomAccessIterator, class OutputIterator, class Distance>
inline OutputIterator
__copy_d(RandomAccessIterator first, RandomAccessIterator last, //雙向可執行,以n為執行次數,速度快
OutputIterator result, Distance*)
{
for (Distance n = last - first; n > 0; --n, ++result, ++first)
*result = *first;
return result;
}
所以可以直接呼叫ostream_iterator的物件,進行文字輸出
同時copy函式中的++first操作,也會呼叫istream_iterator物件的++操作,對文字進行輸入,在第一個copy函式中的inserter引數為iterator adpapters,可以將賦值操作轉換為插入操作,將輸入內容插入到deque中。
參考書籍
《STL原始碼剖析》侯捷著