3

STL で使用される関数オブジェクトは、関数のように操作できる単純なオブジェクトであることは知っていました。関数と関数オブジェクトの働きは同じだと言えます。それが本当なら、なぜ関数ではなく関数オブジェクトを使用する必要があるのでしょうか?

4

4 に答える 4

6

主な利点は、関数オブジェクト (ファンクター) への呼び出しが一般的にインライン化可能であるのに対し、関数ポインターへの呼び出しは一般的にインライン化できないことです (主な例は Cqsortと C++ の比較ですstd::sort)。重要なオブジェクト/コンパレーターの場合、C++ は C の並べ替えのパフォーマンスを低下させる必要があります。

他にも利点があります。たとえば、状態をファンクターにバインドまたは保存できますが、生の関数では実行できません。

直接参照がないことをお詫びします が、Scott Meyers は特定の状況下で 670% の改善を主張しています: qsort と std::sort のパフォーマンス?

編集2 パフォーマンスノートのある一節は次のとおりです。

関数ポインターのパラメーターがインライン化を禁止するという事実は、長年の C プログラマーがしばしば信じがたいと感じる観察を説明しています。C++ の並べ替えは、事実上、速度に関しては C の qsort を困惑させます。確かに、C++ には、インスタンス化するための関数とクラスのテンプレートと、C が単純な関数呼び出しを行う間に呼び出すための変な形の operator() 関数がありますが、C++ の「オーバーヘッド」はすべてコンパイル中に吸収されます。実行時に、sort はその比較関数のインライン呼び出しを行います (比較関数がインラインで宣言されており、その本体がコンパイル中に使用可能であると仮定します) 一方で、qsort はポインターを介してその比較関数を呼び出します。最終的に、ソートの実行速度が向上します。100 万個の double のベクトルに対する私のテストでは、最大 670% 高速に実行されましたが、私の言葉を鵜呑みにするのではなく、自分で試してみてください。

-Scott Meyers "Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library" - Item 46
于 2013-05-04T02:03:46.890 に答える
2

関数に対する関数オブジェクトの利点は、状態を保持できることです ( wikipediaから):

#include <iostream>
#include <iterator>
#include <algorithm>

class CountFrom {
private:
  int &count;
public:
  CountFrom(int &n) : count(n) {}
  int operator()() { return count++; }
};

int main() {
  int state(10);
  std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 11, CountFrom(state));
  return 0;
}

通常の関数は、関数オブジェクトのように状態を保持できません。私の記憶が正しければ、ラムダとクロージャーを持たないことを回避する方法でした(C++ 11ウィキペディアのセクションの前)...

于 2013-05-04T02:14:46.247 に答える
1

ファンクターの一番いいところは、情報を内部に保存できることだと思います。がなかった当時はstd::bind、 などの特定のルーチンに渡すことができるように、多くの単項比較関数を作成する必要がありましたremove_if

于 2013-05-04T02:15:13.580 に答える
0

http://cs.stmarys.ca/~porter/csc/ref/stl/function_objects.htmlを参照してください。

STL は、関数オブジェクト (ファンクター) をコンテナーの並べ替え/検索のコールバックとして使用します。ファンクターはテンプレートであるため、クラスとして実装する方が簡単です。関数ポインタで言っgreater<T>てみてください... STLのコンテナもテンプレートであることを考慮してください。

于 2013-05-04T01:59:16.850 に答える