参考函数语法 - 有和没有&

Can*_*hiu 8 c++

有什么区别

typedef void (&FunctionTypeR)();
Run Code Online (Sandbox Code Playgroud)

VS

typedef void (FunctionType)();
Run Code Online (Sandbox Code Playgroud)

第二个也是功能的参考吗?是FunctionTypeR相当于FunctionType&作为参数的类型时?

对于

void foo(FunctionType bar)
Run Code Online (Sandbox Code Playgroud)

在调用foo时,运行时是否复制了参数栏(函数)?

Naw*_*waz 13

不同之处在于您无法创建函数类型的对象,但您可以创建函数指针类型的对象和函数引用类型.

这意味着如果你有一个功能,比如说f():

 void f(){}
Run Code Online (Sandbox Code Playgroud)

那么这就是你能做什么,你不能做什么:

FunctionType  fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok 
FunctionTypeR fun3 = f; //ok
Run Code Online (Sandbox Code Playgroud)

测试代码:

typedef void (&FunctionTypeR)();
typedef void FunctionType();

void f(){}

int main() {
        FunctionType  fun1 = f; //error - cannot create object of function type
        FunctionType *fun2 = f; //ok 
        FunctionTypeR fun3 = f; //ok
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在看到编译错误(和警告):

 prog.cpp: In function ‘int main()’:
 prog.cpp:7: error: function ‘void fun1()’ is initialized like a variable
 prog.cpp:8: warning: unused variable ‘fun2’
 prog.cpp:9: warning: unused variable ‘fun3’
Run Code Online (Sandbox Code Playgroud)

在线演示:http://ideone.com/hpTEv


但是,如果FunctionType在函数参数列表中使用(这是函数类型),则:

void foo(FunctionType bar);
Run Code Online (Sandbox Code Playgroud)

那相当于

void foo(FunctionType * bar);
Run Code Online (Sandbox Code Playgroud)

这意味着,无论你写什么,你都可以使用baras 调用函数:

   bar();  //ok
 (*bar)(); //ok 
Run Code Online (Sandbox Code Playgroud)

也就是说,你可以这样写:

void h(FunctionType fun) { fun(); }
void g(FunctionType fun) { (*fun)(); }
Run Code Online (Sandbox Code Playgroud)

演示:http://ideone.com/kwUE9

这是由于函数类型对函数指针类型的调整; 即,功能类型调整成为一个函数指针类型:

Function type     |  Function pointer type (adjusted type)
   void ()        |     void (*)()
   void (int)     |     void (*)(int)
   int  (int,int) |     int  (*)(int,int)
   ....           |      ... so on
Run Code Online (Sandbox Code Playgroud)

C++ 03标准在§13.1/ 3中说,

仅在那一个中​​不同的参数声明是函数类型而另一个是指向相同函数类型的指针是等效的.也就是说,调整函数类型以成为函数类型的指针(8.3.5).

[Example:
    void h(int());
    void h(int (*)()); // redeclaration of h(int())
    void h(int x()) { } // definition of h(int())
    void h(int (*x)()) { } // ill-formed: redefinition of h(int())
]
Run Code Online (Sandbox Code Playgroud)

如果您使用`FunctionTypeR(这是一个函数引用类型):

void foo(FunctionTypeR bar);
Run Code Online (Sandbox Code Playgroud)

那它相当于:

void foo(FunctionType * & bar);
Run Code Online (Sandbox Code Playgroud)

和,

void h(FunctionTypeR fun) { fun(); }
void g(FunctionTypeR fun) { (*fun)(); }
Run Code Online (Sandbox Code Playgroud)

演示:http://ideone.com/SmtQv


有趣的部分......

您可以使用FunctionType 声明一个函数(但不能定义它).

例如,

struct A
{
   //member function declaration. 
    FunctionType f; //equivalent to : void f();
};

void A::f() //definition
{
  std::cout << "haha" << std::endl;
}

//forward declaration
FunctionType h; //equivalent to : void h();

int main() {
        A a;
        a.f(); //call member function
        h();   //call non-member function
}

void h() //definition goes below main()
{
   std::cout <<"hmmm.." << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

演示:http://ideone.com/W4ED2

  • 这个答案中有一些微妙的错误.例如,`FunctionType f`是正确的,并且它声明了一个具有适当签名的函数,不正确的是尝试从不同的函数初始化它,所以问题在于`= f`部分,就像你不能do:`void function()= f;`,这使*有趣的部分*不那么令人惊讶或有趣.没有*等价属性*(作为名词),你所说的通常被称为*衰变*(函数标识符衰减成指针,因为数组也会衰减到指针) (2认同)