2

私は最近、次のようなコードの一部に出くわしました。

static typename handle_set::iterator find(T* p)
        {
        return std::find_if(handles().begin(), handles().end(), [p](const std::unique_ptr<T,D>& l) { return l.get() == p; });
        }

どこ

typedef typename std::set<std::unique_ptr<T,D>> handle_set;
    static handle_set& handles(void)
    {
        static handle_set h_;

        return h_;
    }

私の質問はこの部分についてです:

[p](const std::unique_ptr<T,D>& l) { return l.get() == p; }

これは関数の3番目の引数ですstd::find_if()。3番目の引数は関数ポインターにすることができます。これは、別の関数の引数で関数ポインターを定義するインラインの方法ですか?私はこれまでこの種の使用法を見たことがありません。私の理解は正しいですか?

ありがとう。

4

4 に答える 4

3

std::find_ifテンプレート化され、3番目の引数として汎用ファンクター(「関数オブジェクト」とも呼ばれます)を受け入れます。これは、関数として呼び出すことができるものです。このクラスの「things」には、関数ポインター、関数呼び出し演算子およびラムダをオーバーロードするオブジェクトが含まれます。

この特定のケースでは、ラムダ関数で使用されていることがわかります。ラムダ関数は、所定の場所で定義された無名関数です。

ラムダは単なる「関数ポインタを定義する方法」ではありません。代わりに、指定されたコードとキャプチャされたコンテキストを使用して「オンザフライ」で関数オブジェクトを作成します。ラムダと「通常の関数」の主な違いは、ラムダがコンテキスト(この例では変数)をキャプチャできるという事実ですp

また、同じシグニチャを持つ関数へのポインタは同じ型を持ち、ラムダは指定されていない型を持ちます。それでも、何もキャプチャしないラムダは、暗黙的に通常の関数ポインターに変換されます(C++11§5.1.2/6を参照、 Cheersとhthに感謝します。-これを指摘してくれたAlf ); これにより、関数ポインターのみを受け入れ、ジェネリック関数を受け入れない関数でも使用できるようになります。

ラムダはC++言語に最近追加されたものであるため、おそらくまだ見たことがないでしょう(ラムダは、今年承認されたC ++ 11標準で標準化されています)。

于 2012-08-21T00:27:57.633 に答える
1

3番目の引数は関数ポインターではありません。関数オブジェクトです。そのオブジェクトはたまたまポインタである可能性があります。しかし、そうではないかもしれません。。を持つ任意の値にすることができますoperator()。ラムダはそのような値です。

于 2012-08-21T00:25:48.720 に答える
1

これはC++11ラムダ(無名関数)です。

于 2012-08-21T00:26:12.657 に答える
1

C++11コードを見つけたようです。あなたはそこでいくつかのことを扱っています:

  1. ラムダ関数
  2. ユニークなポインタ
  3. クロージャ

そのコードが何をするのかを正確に理解するには、ある程度の読み上げを行う必要があります。

于 2012-08-21T00:33:01.507 に答える