【问题标题】:What is the difference between these two expressions这两个表达有什么区别
【发布时间】:2021-11-15 07:37:30
【问题描述】:
#include <bits/stdc++.h>
using namespace std;
void test(){
    int a = 100;
    cout << a << endl;
}
int main()
{
    void(*b)() = test;
    (*b)();         //expression one
    b();            //expression two
    return 0;
}

test 是一个指向函数的指针,不是吗? (*b)() 是正确的形式,因为它等价于函数原型。但是为什么删除符号* 是正确的呢?他们都产生了正确的结果。

【问题讨论】:

标签: c++


【解决方案1】:

test 是指向函数的指针,不是吗?

不,不是。 test 是一个函数。

b 是一个函数指针。

但是为什么删除符号*是正确的呢?

因为您还可以在函数指针上调用函数调用运算符,而不仅仅是函数。

此外,由于函数可以隐式转换为函数指针,这也是等价的:

(********b)();

这两个表达有什么区别

通过函数指针间接调用函数调用运算符——调用指向的函数。

另一个在函数指针上调用函数调用运算符 - 它通过指针隐式间接调用并调用指向的函数。

前者需要多写3个字符。

【讨论】:

    【解决方案2】:

    test是函数,b是指向函数的指针(指向test);而pointer to function可以直接用在函数调用表达式中。

    函数指针可以用作函数调用运算符的左操作数,这会调用指向的函数:

    取消对函数指针的引用会产生标识指向函数的左值:

    int f();
    int (*p)() = f;  // pointer p is pointing to f
    int (&r)() = *p; // the lvalue that identifies f is bound to a reference
    r();             // function f invoked through lvalue reference
    (*p)();          // function f invoked through the function lvalue
    p();             // function f invoked directly through the pointer
    

    取消对b 的引用,例如*b,您将获得指向函数test。作为效果,(*b)(); 和 b(); 做同样的事情,即调用 test。

    【讨论】:

      【解决方案3】:

      test 是一个指向函数的指针,不是吗?

      test 不是指向函数的指针。这是一个函数。

      要使函数和函数指针之间的区别更加明显,请考虑以下代码 sn-p。

      using Fn = void();
      using FnPtr = void ( * )( );
      
      Fn test;
      FnPtr test_ptr = test;
      
      void test()
      {
          int a = 100;
          std::cout << a << std::endl;
      }
      

      在这段代码 sn-p 中引入了两个别名。第一个别名Fn 表示函数类型void()。第二个别名FnPtr表示指针类型void( * )()。

      所以这条记录

      Fn test;
      

      在此记录时声明函数test

      FnPtr test_ptr = test;
      

      声明由函数测试地址初始化的函数指针test_ptr,因为在此声明中用作初始化器的函数指示符test被隐式转换为指向函数test的指针。您也可以通过以下方式重写声明

      FnPtr test_ptr = &test;
      

      显式应用运算符的地址。

      这两个函数调用表达式

      (*b)();
      b(); 
      

      仅在一个方面有所不同。

      在第一次调用中使用了一个函数左值。从左值到函数指针的隐式转换都没有完成。

      在第二次调用中使用了一个函数指针。

      来自 C++ 14 标准(5.2.2 函数调用)

      1. ...对于非成员函数或静态成员函数的调用, 后缀表达式应该是一个左值,它引用一个 函数(在这种情况下,函数到指针的标准转换 (4.3) 在后缀表达式上被抑制),或者它应该有 指向函数类型的指针

      注意,你也可以通过以下方式调用该函数

      ( *test )();
      

      在这种情况下,函数指示符被隐式转换为指向函数的指针,然后在应用运算符 * 后获得函数的左值。 S 你甚至可以写

      ( ******test )();
      

      或

      ( *&*&*&test )();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-13
        • 2020-01-12
        • 2012-06-12
        • 2016-10-06
        相关资源
        最近更新 更多