2013-05-24 4 views
12

通常のSTL構築物があるとの仕事をコピーします。我々は、ベクターへのstd入力(CIN)からコピーするistream_iteratorを使用ははstd ::どのようストリームイテレータ

vector<string> col; 
copy(istream_iterator<string>(cin), istream_iterator<string>(), 
    back_inserter(col)); 

誰でもこのコードの仕組みを説明できますか?少し微調整とニコライM. Josuttis氏によるとチュートリアルを参照:下記のC++標準ライブラリから引用された解答の

istream_iterator<string>(cin), istream_iterator<string>() 
+1

"The C++ STL" –

答えて

21

まず、std::copyを実際に使用する必要はありません。

vector<string> col((istream_iterator<string>(cin)), 
        istream_iterator<string>()); 

これはおそらくコードを理解しやすくするものではありません。

コードがどのように動作するかは、思ったよりもはるかにストレートです。

template <class T> 
class istream_iterator { 
    std::istream *is; 
    T data; 
public: 
    istream_iterator(std::istream &is) : is(&is) { ++(*this); } 
    istream_iterator() : is(nullptr) {} 

    T operator++() { (*is) >> data; return *this; } 
    T operator++(int) { (*is) >> data; return *this; } 

    T const &operator*() { return data; } 

    bool operator !=(istream_iterator &end) { return (*is).good(); } 
    bool operator ==(istream_iterator &end) { return !(*is).good(); } 
}; 

は明らかに多くの私はスキップてる以上ありますが、それは私たちがここで気に何のほとんどです:istream_iteratorは次のようにぼんやりと見えます。では、イテレータを作成すると、ストリームから項目dataに読み込まれた(またはしようとする)項目が読み込まれます。イテレータを参照解除すると、dataが返されます。イテレーターをインクリメントすると、イテレーターはファイルから次の項目を読み取ります(または試みます)。あるイテレータを別のイテレータと比較しているかのように書かれているにもかかわらず、operator==operator!=は、実際にはファイルの最後をチェックします。その後、std::copyで使われています

、漠然とこのようになりますこれは(再び簡体字):だから

template <class InIt, class OutIt> 
void std::copy(InIt b, InIt e, OutIt d) { 
    while (b != e) { 
     *d = *b; 
     ++b; 
     ++d; 
    } 
} 

、これは読み込み、項目入力イテレータから、出力イテレータにその項目を書き込み、およびまで繰り返し現在の位置のイテレータは、入力の最後のイテレータと同じです(ファイルの最後に到達すると発生します)。他のイテレータとは異なり、istreamイテレータで使用できる唯一の "end"位置はファイルの終わりです。


  1. 技術的には、これは動作が適合していないことに注意してください。物事を単純に保つために比較を単純化しました。 2つのデフォルト構築イテレータは等価を比較する必要があり、同じストリームから2つのイテレータを作成する場合は、少なくともストリームから何かを読み込む前にequalを比較する必要があります。実際の使用で見られる唯一の比較は、あなたがまだファイルの終わりに達しているかどうかを判断することです。
+0

ストリームオペレータはコピー可能ですか? –

+0

@quant_dev:ストリームイテレータを意味しますか?もしそうなら、そうですが、それほど効果はありません。具体的には、イテレータをコピーして参照解除することができますが、イテレータをインクリメントするとすぐに、インクリメントしたもの以外のコピーを参照解除するとUBになります。 –

5

パート:

私の問題は、私は本当にこの部分を理解していないということです。

発現

istream_iterator<string>(cin) 

は、標準的な入力ストリームcinから読み出した文字列イテレータを作成します。テンプレート引数stringは、ストリームイテレータがこのタイプの要素を読み込むように指定します。これらの要素は、通常の入力演算子>>で読み取られます。したがって、アルゴリズムは次の要素を処理することを望むたびに、のIStream反復子は、文字列の入力操作者は通常空白で区切られた1つのワードを読み出す

cin >> string 

の呼び出しにその願望を変換します。

表現

istream_iterator<string>() 

は、いわゆるストリームの終わりイテレータを作成したIStreamイテレータのデフォルトコンストラクタを呼び出します。これはあなたがもはや読むことができないストリームを表します。文字列の終りのイテレータはend of the rangeとして使用されるため、アルゴリズムcopyは、それ以上読み取れなくなるまで、すべての文字列をcinから読み取ります。

最後:back_inserterドキュメントに従って

back_inserter(col)) 

のstd ::容器C

の最後に要素を追加するために使用することができるback_insert_iterator

文字列の読み込みをすべてcolに追加します。

詳細についてはstd::istream_iteratorstd::back_inserterに関する情報があります。

関連する問題