2015-11-11 8 views
5

C++で関数をパラメータとして渡す方法を検索するとき、関数ポインタを使用する例しか見つけられません。しかし、以下はVisual Studioで "g20"をコンパイルして出力します。あなたがstd::function<>の代わりに、関数ポインタを好むかもしれないC++がポインタなしのパラメータとして機能する

#include <iostream> 

using namespace std; 

int f(void fun()); 
void g(); 

int main() { 
    cout << f(g); 
} 

void g() { 
    cout << "g"; 
} 

int f(void fun()) { 
    fun(); 
    return 20; 
} 
+1

どちらの形式も同等です。 –

+0

http://stackoverflow.com/q/26559758/3235496とhttp://stackoverflow.com/q/30354108/3235496を参照してください。 – manlio

答えて

4

f(void (*fun)()); 

代わりの

f(void fun()); 

私の例:それはこのようにFを宣言することをお勧めします。関数ポインタだけでなく、ラムダ、バインド式、関数オブジェクト(オブジェクトはoperator())などを格納することができます。特に、lambdaはAPIをより使いやすくします。

int f(std::function<void()>& fun) { 
    fun(); 
    return 20; 
} 
+0

参照で 'std :: function'を渡すことは、私の経験では通常必要ありません。その型は関数ポインタのように動作するので、値渡しも可能です。 – amon

+1

@amon AFAIK 'std :: function <>'コピーコンストラクタはターゲットをコピーします。これは関数ポインタでは問題ありませんが、関数オブジェクトや値でキャプチャされた要素を持つラムダでは高価かもしれません。 – cdonat

+0

非const参照の使用が正しくありません。値渡しまたはconst参照渡しのいずれかを使用します。 – smerlin

0

std:::functionのシンプルでコストがかからない別の方法は、テンプレートを使用することです。

template <typename Function> 
int f(Function function) { 
    function(); 
    return 20; 
} 

このようにして、タイプは任意の種類の呼び出し可能オブジェクトであると推定されます。できるだけコンパイラが呼び出しをインライン化できるようにする必要があります(std::functionでは不可能です)。

0

どちらの形式も同等です。私は、パラメータがポインタであることを明示的に示す形式を好む。あなたが引数としてNULL,nullptrまたは0の値を渡すことができるので、パラメータがポインタであるという知識は重要です。あなたのプログラムはコンパイルされますが、誰かがf(0)という関数呼び出しを行うとクラッシュします。 NULL,nullptrまたは0引数で関数が呼び出されないことが確実でない限り、ポインターを呼び出す前に、関数ポインターがヌルポインターではないかどうかを常に確認する必要があります。

プロジェクトでlambdaを使用する場合は、 `templatesを使用する必要があります。そうしないと、生の関数ポインタを使用し続けますが、(必要な場合)、あなたの関数ポインタをチェックしていることを確認してください

template <typename Function> 
int f(const Function& functionp) { 
    if(functionp) 
    functionp(); 
    return 20; 
} 

ラムダとstd::function<>オブジェクトもbool演算子を持っているので、ラインif(functionp)はまた、これらのために働くだろうことができます。 nullptrを含むstd::function<>オブジェクトの場合はfalseと評価され、そうでない場合はstd::function<>オブジェクトとlambdaの場合はtrueと評価されます。

0

アンペアンド&は、参考にします。std::decay_tは、参照をポインタにします。

template <class R, class Args...> 
using func_ref_t = R(&)(Args...) 

template <class R, class Args...> 
using func_ptr_t = R(&)(Args...) 
0

C(およびC++)標準によれば、パラメータに関数型がある場合、コンパイラはそれを対応する関数ポインタ型に自動的に調整します。したがって、コンパイラに関する限り、2つは同じです。

C99標準セクション6.7.5.3段落8:

パラメータの宣言 '関数復帰型「としては、」 6.3のように、「」タイプを返す関数へのポインタ「」に調整しなければなりません2.1。

C++ 03標準セクション8.3.5段落3:復帰

[...]、 タイプの任意のパラメータの各パラメータの型を決定した後、[...]「機能T "はそれぞれ[...]" 関数へのポインタ "に調整されます。 [...]

関連する問題