std :: function <>と標準関数ポインタの違いは何ですか?あるstd :: function <>と標準関数ポインタの違いは?
:
typedef std::function<int(int)> FUNCTION;
typedef int (*fn)(int);
は、彼らが効果的に同じものはありますか?
std :: function <>と標準関数ポインタの違いは何ですか?あるstd :: function <>と標準関数ポインタの違いは?
:
typedef std::function<int(int)> FUNCTION;
typedef int (*fn)(int);
は、彼らが効果的に同じものはありますか?
関数ポインタは、C++で定義された実際の関数のアドレスです。 std::function
は、任意のタイプの呼び出し可能オブジェクト(関数のように使用できるオブジェクト)を保持できるラッパーです。ここで
struct FooFunctor
{
void operator()(int i) {
std::cout << i;
}
};
// Since `FooFunctor` defines `operator()`, it can be used as a function
FooFunctor func;
std::function<void (int)> f(func);
は、std::function
は、それはあなたが、あなたはちょうどそれがvoid
を返し、1 int
パラメータを持っていることを知って、それはFooFunctor
だかわからない—を扱っているが何であるかを呼び出し可能なオブジェクトの種類離れて正確に抽象化することができます。
この抽象化が有用な実際の例は、C++を別のスクリプト言語とともに使用している場合です。 C++で定義された関数とスクリプト言語で定義された関数を汎用的に扱うことができるインターフェイスを設計することもできます。
編集:std::function
と並ん
バインディング、あなたもstd::bind
を見つけるでしょう。これらの2つは、一緒に使用すると非常に強力なツールです。その例で
void func(int a, int b) {
// Do something important
}
// Consider the case when you want one of the parameters of `func` to be fixed
// You can used `std::bind` to set a fixed value for a parameter; `bind` will
// return a function-like object that you can place inside of `std::function`.
std::function<void (int)> f = std::bind(func, _1, 5);
、bind
によって返される関数オブジェクトは、最初のパラメータをとり_1
、及びa
パラメータとしてfunc
に渡し、そして一定5
ことがb
を設定します。
1つは関数ポインタです。もう1つは関数ポインタのラッパーとして機能するオブジェクトです。
彼らはかなりは同じことを表しますが、std::function
はあなたがバインディングやその他もろもろを作るのですかできるように、はるかより強力です。
std::function
に状態があります。それはそれに "束縛された"追加のパラメータを保持することができます。
これらのパラメータは、他のクラス、他の関数、またはメンバー関数呼び出し用のこのポインタのようなものまでさまざまです。
置換関数ポインタは、それがvoid*
がstd::function
に隠されることになる状態をreperenstingと、typedef int (*fn)(void*,int);
あるtypedef int (*fn)(int);
ありません。
これらは全く同じではありません。 std::function
は複雑で重く、ステートフルなマジックタイプであり、あらゆる種類の呼び出し可能なエンティティを保持することができますが、関数ポインタは単純なポインタです。あなたがそれを取り除くことができるならば、裸の関数ポインタかauto
- bind
/auto
-lambdaタイプを好むべきです。ファンクション、ファンクタ、ラムダとバインド式のキャプチャなど、呼び出し可能なエンティティの異種コレクションを体系的に編成する体系的な方法が本当に必要な場合は、std::function
を使用してください。
更新:auto
種類についての説明のビット:次の2つの関数の比較:
void do_something_1(std::function<void(int)> f, int a) { f(a); }
template <typename F, typename A> void do_something_2(F f, A a) { f(a); }
は今ラムダまたはbind
表現でそれらを呼び出す想像:
do_something_X([foo, &bar](int n){ bar += n*foo; }, 12);
do_something_X(std::bind(X::bob, &jim, true, _1, Blue), 13);
テンプレートを使用した2番目のバージョンのほうが効率的です。どちらの場合も、引数F
は実際の、知られていないタイプの式に導かれます。 std::function
の最初のバージョンはテンプレートではなく、より単純でより慎重に見えるかもしれませんが、は常にオブジェクトを構築し、複数タイプの消去と仮想ディスパッチコストを伴う可能性があります。
これはちょっと混乱しています。 つまり、正確にstd :: functionを使用するタイミングと、関数ポインタを使用するタイミングです。また、自動バインド/オートラムダ型とは何ですか? – aCuria
@aCuria:呼び出し可能なもののコンテナを作成し、そこにさまざまな種類の混合型を入れたい場合は、 std :: function'を呼び出してすべてを変換します。しかし、あなたが常に本物のフリー関数を持っていることを知っていれば、関数ポインタのコンテナを作ることができます。実際の投稿の自動設定を少し拡大します。 –
@aCuria:更新済み! –
ここに_1は何ですか? – makar
@makarこれは、結果の関数の第1引数を参照するために 'std :: bind'によって使用される識別子です。これは少し似ています: 'void bound(int _1){func(_1、5); } '。 –
[ここのリンク](http://stackoverflow.com/questions/25848690/should-i-use-stdfunction-or-a-function-pointer-in-c)関数ポインタとstd :: functionの間に別の違いがあります:ラムダキャプチャを関数ポインタで使用することはできません。ラムダ '[&](int a、int b){/ * blah * /}'または '[=](int a、int b){/ * blah * /} 'を実行すると、コンパイルエラーが発生します。有効な形式は '[](int a、int b){/ * blah * /}' – r0ng