5

この短いコードスニペットがあります。この構造が何を意味するのかわかりません。このコードスニペットは、入力から数値を読み取り、unordered_mapでその頻度をカウントすることを知っています。しかし、何[&]ですか?そして、の意味は(int x)何ですか?何のinput(cin)略ですか?かっこ内の「cin」を意味しますか?そして、for_eachはどのようinput(cin)にしてeofパラメーターを空にするまで反復できますか?私はこの全体の構造を理解していません。

unordered_map<int,int> frequency;
istream_iterator<int> input(cin);
istream_iterator<int> eof;

for_each(input, eof, [&] (int x)
    { frequency[x]++; });
4

3 に答える 3

6

istream_iteratoristreamコンストラクターに渡すからアイテムを繰り返し抽出できます。オブジェクトは次のeofように説明されます。

この反復子には特別な値が存在します: ストリームの終わり。イテレータがこの値に設定されている場合、ストリームの最後に到達したか (ストリームに適用された演算子 void* は false を返します)、デフォルトのコンストラクタを使用して構築されています (basic_istream オブジェクトに関連付けられていません)。

for_eachは、イテレータ #1 を取り、イテレータ #2 と等しくなるまでインクリメントするループ構造です。ここでは、標準入力をラップするイテレータをcin使用して、消費する入力がなくなるまでそれをインクリメントします (アイテムの抽出に変換されます)。これにより、input比較が等しくeofなり、ループが終了します。

構成体[&] (int x) { frequency[x]++; }無名関数です。関数をインラインで記述する簡単な方法です。ほぼ同じ効果が得られます

unordered_map<int,int> frequency; // this NEEDS to be global now
istream_iterator<int> input(cin);
istream_iterator<int> eof;

void consume(int x) {
    frequency[x]++;
}

for_each(input, eof, consume);

簡単に言えば、このコードは、利用可能なデータがすべて消費されるまで標準入力から整数を読み取り、マップ内の各整数の出現頻度のカウントを保持します。

于 2012-09-26T08:47:49.373 に答える
2

あなたの質問には2つの部分があります。

  1. 最初のものは、ストリーム イテレータに関するものです。Anstd::istream_iterator<T>は some から構築されstd::istream & s、逆参照すると のように動作し{ T x; s >> x; return x; }ます。抽出が失敗すると、イテレータはデフォルトで構築されたイテレータと等しくなり、「終了」イテレータとして機能します。

    ストリーム イテレータを使用すると、ストリームをトークンのコンテナとして扱うことができます。例えば:

    std::vector<int> v(std::istream_iterator<int>(std::cin),
                       std::istream_iterator<int>());
    
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
    
  2. C++11 では、無名関数またはファンクター (クロージャーと呼ばれる) を定義するラムダ式が導入されています。簡単なものは次のようになります。

    auto f = [](int a, int b) -> double { return double(a) / double(b); };
    
    auto q = f(1, 2);  // q == 0.5
    

    これfは通常のフリー関数として記述できますが、フリー関数は名前空間スコープで、またはローカル クラスの静的メンバー関数として出現する必要がありました。(これが実際にラムダ式の型です!) ラムダ式の型は不明であり、 newautoキーワードを介してのみ取得できることに注意してください。

    ラムダは、周囲の状態をキャプチャできる複雑な関数オブジェクトとして機能すると、より便利になります。あなたの例は次のように書くことができました:

    auto f = [&frequency](int x) -> void { ++frequency[x]; };
    

    最初の角括弧の間に表示される変数がキャプチャされます。このラムダは、次のローカル クラスおよびオブジェクトと同等です。

    struct F
    {
        F(std::unordered_map<int, int> & m) : m_(m) { }
        void operator()(int x) { ++m_[x]; }
    private:
        std::unordered_map<int, int> & m_;
    } f;
    

&キャプチャ リストに含まれていない変数は、値によってキャプチャされます。つまり、クロージャ オブジェクトでコピーが作成されます。簡単に言うと、値または参照によって、すべてを[=]それぞれキャプチャまたは[&]キャプチャすることができます。

于 2012-09-26T09:03:27.313 に答える
1

これは STL std::for_each (非 C++11)がeofと等しくなるまで入力を反復します。各値に対してラムダを呼び出す[&] (int x) { frequency[x]++; }

したがって、このコードは istream 内の文字の頻度を計算します。それらをマップに保存する

于 2012-09-26T08:46:52.993 に答える