【问题标题】:function pointer assignment and call in c++?c++中的函数指针赋值和调用?
【发布时间】:2016-02-05 03:06:37
【问题描述】:

我知道当我们使用函数名作为值时,函数会自动转换为指针。 看下面的代码:

int print(int a)
{
    return a;
}

int main()
{
    int (*p)(int) = print;
    int (*q)(int) = &print;

    cout << p(8) << endl;
    cout << (*p)(8) << endl;
}

为什么int (*p)(int) = print;print是指针,而int (*p)(int) = &amp;print;&print是指针的地址,等价?

另一方面,当我们使用指向函数的指针来调用函数时,为什么p(8)(*p)(8) 是等价的?

【问题讨论】:

  • 我想这只是为了方便,您在使用函数指针调用函数时不必显式取消引用函数指针。如果您使用typedefs,您可以使用函数指针而不使用任何*,恕我直言非常好
  • @SimonKraemer 谢谢。但是链接只解释了取消引用,我的问题还包括函数指针的分配。

标签: c++ function pointers


【解决方案1】:

print不是指针。它的类型是int(int),而不是int(*)(int)。这种区别在类型推导中尤为重要

auto& f = print;   //type of f is int(&)(int), not int(*(&))(int)
template<typename Func>
foo(Func& f);
foo(print);  //Func is deduced to be int(int), not int(*)(int)

类似于数组,您不能“按值”复制函数,但可以传递其地址。例如,

int arr[4];     //the type of arr is int[4], not int*
int *a = arr;   //automatic array-to-pointer decay
int (*a)[4] = &arr;  //type match 
int (*p)(int) = print;  //automatic function-to-pointer decay
int (*p)(int) = &print; //type match

现在,当您通过p 致电print 时,

p(8)     //automatic dereferencing of p
(*p)(8)  //manual dereferencing of p

【讨论】:

  • 你的回答有点道理。但是在c++入门第5版这本书和许多其他网站教程中说使用函数名作为右值会将其转换为指针。所以不知道你的回答是不是函数指针赋值的特殊条件。
  • @sydridgm 他们是正确的。他们指的是我的回答中的函数到指针的衰减。
【解决方案2】:

print 是一个函数,但它可以隐式转换为函数指针类型。引用自cppref

指针函数
函数类型 T 的左值可以隐式 转换为指向该函数的纯右值指针。这不适用 到非静态成员函数,因为左值引用 非静态成员函数不存在。

所以,在你的情况下:

int (*p)(int) = print; // Conversion happens.
int (*q)(int) = &print; // Conversion does not happen.

当需要编译程序时会自动启动隐式转换,否则不会应用。

关于函数调用,是关于内置函数调用运算符()。根据cppref,内置函数调用运算符适用于引用函数的左值表达式和指向函数的指针。在你的情况下:

p(8); // The function call operator is applied to a pointer to function.
(*p)(8); // The function call operator is applied to an lvalue reference to function.

供您参考(强调我的):

内置函数调用运算符
函数调用表达式,例如 E(A1, A2, A3),由 命名函数的表达式,E,后跟一个可能为空的 括号中的表达式 A1、A2、A3、... 的列表。表达方式 函数的名字可以是

a) 引用函数的左值表达式
b) 函数指针
...

【讨论】:

    猜你喜欢
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 2011-01-20
    • 2020-09-07
    • 2011-10-27
    相关资源
    最近更新 更多