【问题标题】:Does an implicit conversion from function pointer to function exist?是否存在从函数指针到函数的隐式转换?
【发布时间】:2022-08-24 21:31:26
【问题描述】:

我写这篇文章主要是为了澄清一些关于我在 Stackoverflow 上偶然发现的函数指针的令人困惑/误导性的信息。

让我们从一个例子开始:

#include <iostream>

void func ()
{
    std::cout<<\"func here\"<<\'\\n\';
}

int main()
{
    void (*fp)()=func;
    void (&fref)()=func;

    func();//call through function
    (&func)();//call through function pointer
    (*fp)();//call through function
    fp();//call through function pointer
    fref();//call through function
    (&fref)();//call through function pointer
}

这打印:

func here
func here
func here
func here
func here
func here

可以看出,由于函数到函数指针的衰减cppreference,大多数时候可以使用函数代替函数指针。

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

但除此之外,它看起来还可以使用函数指针代替函数,因为我可以使用它来调用函数而无需显式取消引用。

此外this Stackoverflow answer

另请注意,您不需要使用一元 * 来通过函数指针进行调用;两者 (*p1_foo)();和 (p1_foo)();有同样的结果,同样是因为函数到函数指针的转换。

this Stackoverflow answer

还有一个双重便利:调用位置的函数指针会自动转换为函数值,所以你不必写 * 来通过函数指针调用。

让它看起来好像存在一个指向函数转换的隐式函数指针。

    标签: c++ c function pointers language-lawyer


    【解决方案1】:

    不存在从函数指针到函数的隐式转换。

    根据 ISO 国际标准 ISO/IEC 14882:2020(E) – 编程语言 C++,没有提到这种转换。

    但除此之外,它看起来还可以使用函数指针代替函数,因为我可以使用它来调用函数而无需显式取消引用。

    这可能就是为什么一些 SO 答案(甚至是一些鲜为人知的 C++ 书籍!)得出错误的结论,即函数指针本质上与函数相同,并使用函数来函数指针衰减作为证据。然而,这种隐式转换只能以一种方式工作!这意味着第一个 SO 答案的引用部分不正确。

    为什么函数调用无论如何都会成功?

    为什么我们可以使用函数指针调用函数而无需显式取消引用的原因实际上在于内置函数调用运算符“()”的工作方式cppreference

    命名函数的表达式可以是 a) 引用函数的左值表达式 b) 函数指针 c) 选择成员函数的显式类成员访问表达式 d) 隐式类成员访问表达式,例如在另一个成员函数中使用的成员函数名称。

    啊哈!所以函数调用运算符可以直接将函数指针作为表达式。没有隐式转换。如果您阅读第二个 SO 答案中的引用,它明确提到函数指针需要在呼叫位置使用函数调用运算符调用。

    这也意味着在函数调用之外的所有上下文中,确实需要取消引用函数指针,例如在初始化函数引用时:

    void func ()
    {
        std::cout<<"func here"<<'\n';
    }
    
    int main()
    {
        void (*fp)()=func;//OK (implicit function to function pointer decay)
    
        void (&&fref1)()=&func;//error: invalid initialization of reference of type 'void (&&)()' from expression of type 'void (*)()'
    
        void (&fref2)()=*fp;//OK
    
        void (&fref3)()=fp;// error: invalid initialization of reference of type 'void (&)()' from expression of type 'void (*)()'
    }
    
    

    【讨论】:

      猜你喜欢
      • 2019-06-18
      • 2018-09-25
      • 2013-03-17
      • 2016-08-18
      • 1970-01-01
      • 2013-11-03
      • 2022-12-02
      • 1970-01-01
      • 2015-11-03
      相关资源
      最近更新 更多