C ++標準テンプレートライブラリには、多くのクラスが()
演算子をオーバーロードしている「機能」部分があります。
C ++で関数をオブジェクトとして使用するのに便利ですか?
代わりに関数ポインタを使用できないのはなぜですか?例はありますか?
C ++標準テンプレートライブラリには、多くのクラスが()
演算子をオーバーロードしている「機能」部分があります。
C ++で関数をオブジェクトとして使用するのに便利ですか?
代わりに関数ポインタを使用できないのはなぜですか?例はありますか?
もちろん、関数オブジェクトの代わりに常に関数ポインタを使用できますが、関数オブジェクトには関数ポインタよりも優れた利点があります。
よりよい性能:
最も明確で重要な利点の 1 つは、パフォーマンスが向上する可能性が高いことです。関数オブジェクトの場合、コンパイル時に詳細が利用できるため、コンパイラーは呼び出される関数を正確に決定し、インライン化できます。これは、ポインターのデリファレンスによってコンパイラーが実際の関数を決定することが困難になる関数ポインターの場合とは異なります。それが呼び出されます。
関数オブジェクトはスマート関数です:
関数オブジェクトには、他のメンバー関数と属性がある場合があります。これは、関数オブジェクトに状態があることを意味します。実際、関数オブジェクトで表される同じ関数が、同時に異なる状態を持つ場合があります。これは、通常の機能では不可能です。関数オブジェクトのもう 1 つの利点は、それらを使用または呼び出す前に実行時に初期化できることです。
通常の関数は、シグネチャが異なる場合にのみ異なる型を持つことができます。ただし、関数オブジェクトは、シグネチャが同じであっても異なる型を持つことができます。実際、関数オブジェクトによって定義される各機能動作には、独自の型があります。これは、関数の動作をテンプレート パラメーターとして渡すことができるため、テンプレートを使用したジェネリック プログラミングの大幅な改善です。
代わりに関数ポインタを使用できないのはなぜですか? 例はありますか?
C スタイルの関数ポインターを使用すると、インライン化の利点を活用できません。関数ポインターは通常、ルックアップのために追加の間接参照を必要とします。
ただし、がオーバーロードされている場合、コンパイラがコードを追加して余分な呼び出しを保存するoperator ()
のは非常に簡単なので、パフォーマンスが向上します。inline
オーバーロードのもう 1 つの利点は、関数オブジェクトoperator ()
を暗黙的に引数と見なす関数を設計できることです。別の関数として渡す必要はありません。手作業でコーディングされたプログラムが少ないほど、バグが少なくなり、可読性が向上します。
Bjarne Stroustrup (C++ 発明者) の Web ページからのこの質問は、その側面をうまく説明しています。
C++ 標準 (テンプレート) ライブラリは、必要に応じてオーバーロードされた関数型プログラミングoperator ()
を使用します。
> C++ で関数をオブジェクトとして使用すると便利ですか?
はい: C++ テンプレート メカニズムでは、他のすべての C/C++ プログラミング スタイル (C スタイルと OOP スタイル、以下を参照) が可能です。
>代わりに関数ポインタを使用できないのはなぜですか? 例はありますか?
単純な C 関数ポインターは、適切に定義された operator() を持つオブジェクトでもあります。ライブラリを設計する場合、望ましくない場合にその C ポインター スタイルを使用することを誰かに強制したくありません。通常、すべて/全員に OOP スタイルを強制する/使用するように強制するのと同じくらい望ましくありません。下記参照。
C プログラマーや関数型プログラマーの観点からすると、OOP は遅くなるだけでなく冗長になる傾向があり、ほとんどの場合、抽象化の方向性が間違っています (「情報」は「オブジェクト」ではなく、「オブジェクト」であってはなりません)。そのため、「オブジェクト」という言葉が他の文脈で使用されるたびに、人々は混乱する傾向があります.
C++ では、目的のプロパティを持つものはすべてオブジェクトと見なすことができます。この場合、単純な C 関数ポインターもオブジェクトです。これは、OOP パラダイムが望ましくないときに使用されることを意味するものではありません。テンプレートメカニズムを使用するための適切な方法です。
パフォーマンスの違いを理解するには、プログラミング (言語) スタイル/パラダイムとそれらの可能な最適化を比較します。
C スタイル:
C++ (および Java) OOP スタイル:
C++ テンプレート スタイル:
C++ テンプレートは、上記の他の 2 つのスタイルを可能にするのに十分な汎用性を備えており、インライン化の場合には、それらよりも優れたパフォーマンスを発揮する可能性さえあります…</p>
コンパイルされた関数型言語: (「適切な末尾呼び出し」がないため、JVM と Javascript をターゲット プラットフォームとして除外)
主な違いは、関数オブジェクトは状態を保持できるため、単純な関数ポインターよりも強力であるということです。ほとんどのアルゴリズムは、プレーン関数ポインターではなくテンプレート関数を使用します。これにより、ファンクターまたはC ++ 11の新しいラムダに格納された値で追加の引数を埋めることにより、異なるシグネチャを持つ関数を呼び出すバインダーとして強力な構造を使用できます。アルゴリズムがファンクターを使用するように設計されたら、ライブラリーに事前定義されたジェネリック関数オブジェクトのセットを提供することは理にかなっています。
それとは別に、ほとんどの場合、これらのファンクターは、コンパイラーが完全な定義を持ち、関数呼び出しのインライン化を実行してパフォーマンスを向上させることができる単純なクラスであるという潜在的な利点があります。これが、Cライブラリstd::sort
よりもはるかに高速になる理由です。qsort