C++ “函数到函数指针”;“衰退”;

C++ “函数到函数指针”;“衰退”;,c++,C++,正如我们所知,类似于void()的参数将被重写为void(*)()。这类似于数组到指针的衰减,其中int[]变为int*。在许多情况下,使用数组会将其衰减为指针。除参数外,是否存在函数“衰减”的情况 C++标准状态: §8.3.5/5 。。。在确定每个参数的类型后 类型“T数组”或“函数返回T”调整为“指针 分别指向“T”或“指向返回T的函数的指针” 因为下面的评论者似乎不相信我..下面是我的编译器显示的内容 void handler(void func()) { func(42);

正如我们所知,类似于
void()
的参数将被重写为
void(*)(
)。这类似于数组到指针的衰减,其中
int[]
变为
int*
。在许多情况下,使用数组会将其衰减为指针。除参数外,是否存在函数“衰减”的情况

C++标准状态:

§8.3.5/5

。。。在确定每个参数的类型后 类型“T数组”或“函数返回T”调整为“指针 分别指向“T”或“指向返回T的函数的指针”

因为下面的评论者似乎不相信我..下面是我的编译器显示的内容

void handler(void func())
{
    func(42);
}

main.cpp: In function 'void handler(void (*)())':
main.cpp:5:12: error: too many arguments to function
     func(42);
        ^

是的,它们都是指针,第一个是函数指针,第二个是指向int块的指针。*看起来像一个点。

数组和函数之间的另一个明显相似之处是:

void bar(string message) 
{
    cout << message << endl;
}

void main()
{
    int myArray[10];
    int* p = myArray; //array to pointer to array

    void (*f)(string);
    f = bar; //function to function pointer decay
}
void条(字符串消息)
{

CUT< P>当数据类型时,函数不是C和C++中的第一类公民(问题是C++,而是行为是从C继承的)。它们是代码,不是数据,它们不能被复制,作为函数传递给函数或函数返回(但所有这些都可以发生在函数指针上)。 这就是为什么函数名被视为指向该函数的指针,而不是函数体本身

使用函数(名称)而不是函数指针的可能性只是语言对程序员的一种礼貌,而不是“衰退”

数组也是如此:它们不被复制,不作为函数参数传递,也不由函数返回。而是使用它们的第一个元素的地址(复制、作为函数参数传递或由函数返回)。这就是为什么可以使用数组名而不是其第一个元素的地址,同样,这只是一种编写更少(且更少混淆)代码的方法

对于编译器来说,函数是一个不移动的内存块(包含在某个时间执行的代码),由其地址(即指向函数的指针)标识。数组也是一个数据块 它不移动,由它的地址(也是它的第一个元素的地址)标识。同样,这是一个指针


较高级别(C,C++)的
函数
数组
概念由编译器转换为较低级别(汇编程序,机器代码)理解的基本值(指针).

有三种转换被认为是左值转换:左值到右值、数组到指针和函数到指针。您可以将其称为“衰减”,因为这是
std::detacy
对这些类型所做的,但标准仅将其称为函数到指针转换[conv.func]:

函数类型为
T
的左值可以转换为“指向
T
的指针”类型的PR值。结果是指向函数的指针

如果你问函数到指针转换的情况是什么,它们基本上与其他两个左值转换的情况相同。如果我们按顺序看一下标准,下面是函数到指针转换情况的详尽列表:

将函数用作操作数[expr]/9:

每当glvalue表达式显示为期望该操作数具有prvalue的运算符的操作数时, 应用左值到右值(4.1)、数组到指针(4.2)或函数到指针(4.3)的标准转换 将表达式转换为prvalue

将函数用作varargs函数的参数,[expr.call]/7:

当给定参数没有参数时,传递参数的方式是接收函数可以通过调用
va_arg
(18.10)…获取参数值。对参数表达式执行左值到右值(4.1)、数组到指针(4.2)和函数到指针(4.3)的标准转换

您可以
static\u cast
取消此转换,[expr.static.cast]/7:

任何不包含左值到右值(4.1)的标准转换序列(第4条)的倒数,arrayto- 指针(4.2)、函数到指针(4.3)、空指针(4.10)、空成员指针(4.11)或布尔值(4.12) 转换,可以使用
static\u cast
显式执行

否则,将转换传入的操作数[expr.static.cast]/8:

将左值到右值(4.1)、数组到指针(4.2)和函数到指针(4.3)的转换应用于 操作数

使用
reinterpret\u cast
,[expr.reinterpret.cast]/1:

表达式
reinterpret_cast(v)
的结果是将表达式
v
转换为类型的结果
T
。如果
T
是左值引用类型或函数类型的右值引用,则结果为左值;如果
T
是 对对象类型的右值引用,结果为xvalue;否则,结果为prvalue和左值torvalue (4.1)、数组到指针(4.2)和函数到指针(4.3)的标准转换在 表达式
v

使用
const_cast
,[expr.const.cast],其措辞与上述基本相同。使用条件运算符[expr.cond]:

执行左值到右值(4.1)、数组到指针(4.2)和函数到指针(4.3)的标准转换 在第二个和第三个操作数上

请注意,在上述所有情况下,都是左值转换

在模板中也会发生函数到指针的转换。将函数作为非类型参数传递[temp.arg.nontype]/5.4:

对于指针指向函数类型的非类型模板参数,函数指向指针转换(4.3) 应用

或者