C++輸出流疊代器(STL輸出流疊代器)詳解

2020-07-16 10:04:30
輸出流疊代器是由 ostream_iterator 模板定義的,這個模板的第一個模板引數是被寫值的型別,第二個模板引數是流字元的型別;第二個模板引數預設是 char 型別的值。ostream_iterator 是一個能夠將任意 T 型別物件寫到文字模式的輸出流中的輸出疊代器;只要 T 型別的物件實現了將 T 型別物件寫到流中的 operator<<()。

因為它是一個輸出疊代器,所以它支援前向和後向遞增操作,並且是一個單向傳入的疊代器。輸出流疊代器定義了它的拷貝賦值運算子,因此可以用插入運算子將 T 物件寫到流中。預設的輸出流疊代器會按照 char 字元的序列來寫入值。通過指定第二個模板型別引數,可以寫包含不同型別字元的流。

ostream_iterator 型別定義了下面這些成員函數:
  • 建構函式:第一個建構函式會用作為第一個引數的 ostream 物件的輸出流生成一個開始疊代器,第二個引數是分隔符字串。輸出流物件會在每個被它寫入到流中的物件的後面寫分隔符字串。第二個建構函式可以省略第二個差數,它會生成一個寫物件時後面不跟分隔符的疊代器。
  • operator=(const T& obj) 會將 obj 寫到流中,然後寫分隔符字串,前提是在建構函式中指定了一個。這個函數返回一個疊代器的參照。
  • operator*() 不做任何事,除了返回疊代器物件。為了將疊代器限定為輸出疊代器,這個操作必須被定義。
  • operator++() 和 operator++(int) 都被定義了但不做任何事,除了返回疊代器物件。為了將疊代器限定為輸出疊代器,前向或後向自增操作必須被支援。

不做任何事的運算子函數是必要的,因為它們是說明輸出疊代器可以做些什麼的規範的一部分。如果想寫資料到一個文字模式的流中,並且隨後打算以文字方式讀取,流的值之間就需要分隔符。出於這個原因,儘管可以顯式地寫分隔符,但通常會使用有兩個引數的建構函式。

輸出流疊代器成員函數的使用

下面是一個範例,展示了成員函數可以被使用的各種方式:
// Using output stream iterator function members
#include <iostream>                                      // For standard streams
#include <iterator>                                      // For iterators and begin() and end()
#include <vector>                                        // For vector container
#include <algorithm>                                     // For copy() algorithm
#include <string>
using std::string;

int main()
{
    std::vector<string> words {"The", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"};

    // Write the words container using conventional iterator notation
    std::ostream_iterator<string> out_iter1 {std::cout};   // Iterator with no delimiter output
    for(const auto& word : words)
    {
        *out_iter1++ = word;                                 // Write a word
        *out_iter1++ = " ";                                  // Write a delimiter
    }
    *out_iter1++ = "n";                                   // Write newline

    // Write the words container again using the iterator
    for(const auto& word : words)
    {
        (out_iter1 = word) = " ";                            // Write the word and delimiter
    }
    out_iter1 = "n";                                      // Write newline

    // Write the words container using copy()
    std::ostream_iterator<string> out_iter2 {std::cout, " "};
    std::copy(std::begin(words), std::end(words), out_iter2);
    out_iter2 = "n";
}
這段程式碼以 3 種方式將 words 容器中的元素寫到標準輸出流中。out_iter1 流疊代器通過呼叫只以輸出流為引數的建構函式而生成。第一個迴圈以常規方式輸出疊代器符號,在解除參照後遞增它,並複製 word 的當前值到 out_iter1 的解除參照的結果中。迴圈後面的語句會在流中寫一個新行。注意,不能這樣寫:
out_iter1 = 'n';   // Won't compile!
定義的疊代器會將 string 物件寫入流中,因此它不能寫任何其他型別的資料。成員函數 operator=() 只接受一個 string 引數,因此這條語句無法通過編譯。

像前面描述的那樣,opemtor*() 和前自增及後自增運算子除了返回疊代器的參照外,不會做任何事。因此可以去除這些操作,像第二個迴圈中的語句那樣,不使用它們也可以產生同樣的輸出。為了保證應用分隔符的第二條賦值語句有輸出疊代器作為它的左運算元,語句中的括號是必要的。

第三行的輸出是通過以你在前面的章節中看到過的方式呼叫 copy() 演算法生成的。元素 的值會被複製到 out_iter2 中,定義它的建構函式的第二個引數指定了每個輸出值後面的分隔符字串。