31

以下のコードでは、関数ポインタと私が「関数参照」と見なしたものは同じセマンティクスを持っているようです:

#include <iostream>
using std::cout;

void func(int a) {
    cout << "Hello" << a << '\n';
}
void func2(int a) {
    cout << "Hi" << a << '\n';
}

int main() {
    void (& f_ref)(int) = func;
    void (* f_ptr)(int) = func;

    // what i expected to be, and is, correct:
    f_ref(1);
    (*f_ptr)(2);

    // what i expected to be, and is not, wrong:
    (*f_ref)(4); // i even added more stars here like (****f_ref)(4)
    f_ptr(3);    // everything just works!

    // all 4 statements above works just fine

    // the only difference i found, as one would expect:
//  f_ref = func2; // ERROR: read-only reference
    f_ptr = func2; // works fine!
    f_ptr(5);

    return 0;
}

Fedora/Linux で gcc バージョン 4.7.2 を使用しました

アップデート

私の質問は次のとおりです。

  1. 関数ポインターが逆参照を必要としないのはなぜですか?
  2. 関数参照を逆参照してもエラーにならないのはなぜですか?
  3. どちらか一方を使用しなければならない状況はありますか?
  4. なぜf_ptr = &func;機能するのですか?func はポインターに崩壊する必要があるので?
    Whilef_ptr = &&func;は機能しません ( からの暗黙の変換void *)
4

4 に答える 4

17

関数と関数参照 (つまり、これらの型のid 式) はほとんどすぐに関数ポインターに崩壊するため、式funcf_ref実際には関数ポインターになります。(***func)(5)必要に応じて電話をかけることもでき(******f_ref)(6)ます。

&-operator を関数自体に適用されているかのように動作させたい場合、関数参照を使用することが望ましい場合があります。たとえば&func、 は と同じです&f_refが、別の&f_ptrものです。

于 2013-10-05T17:22:31.203 に答える
14

「なぜ関数ポインタは逆参照を必要としないのですか?」

関数識別子自体は実際には関数へのポインターであるため、次のようになります。

4.3 関数からポインタへの変換
§1 関数型の左辺値は、T「へのポインタ」型の右辺値に変換できますT。結果は関数へのポインタです。

「関数参照を逆参照してもエラーにならないのはなぜですか?」

基本的に、参照の定義は別名 (別名) の定義と見なすことができます。オブジェクトへの参照の作成に関する8.3.2 References in partの標準でも、「参照はオブジェクトの名前と考えることができる」ことがわかります。

したがって、参照を定義する場合:

void (& f_ref)(int) = func;

を使用できるf_refほぼすべての場所で使用できるようになりますfunc。その理由は次のとおりです。

f_ref(1);
(*f_ref)(4);

funcを直接使用する場合とまったく同じように機能します。

func(1);
(*func)(4);
于 2013-10-05T17:37:47.523 に答える