************************************************************************

Dan*_*aum 6 c++ overloading

为什么将函数转换为除返回类型之外相同的函数类型失败相关?,我想以更全面的方式理解函数类型和函数签名之间的区别.

例如,该类型的函数的通常必须与函数指针处理时考虑,并且函数的类型包括该函数的返回类型.

但是,正如Mike Seymour对上述相关问题的回答所述,函数的签名与函数的类型不同.签名当然用于从潜在的重载函数中消除歧义(注意函数的返回类型在识别唯一函数中不起作用).但是,我现在想了解功能签名与功能类型的相关性和重要性.在我看来,C++中函数签名的唯一目的是在重载决策期间识别过载集中的重载候选和/或唯一函数.

我对么?重载解析是C++中函数签名的唯一目的吗?或除了(或仅间接相关)重载决议之外,还有其他功能签名用途/应用吗?

附录为清楚起见,请注意我特别想了解功能签名的目的与功能类型之间的区别.即,我知道函数类型的使用和编译器/链接器的调用约定的实现都需要函数类型.但是,调用约定仅在重载解析完成后才有意义.我在这里问,具体来说,函数签名的唯一目的(与类型相反)是否用于重载解析.

小智 2

我对么?

就我而言,还有其他目的。考虑一下 C 也有函数签名但没有重载。

除了重载之外,函数签名的根本目的是符合调用约定特定平台的

当函数接受参数并返回值时,编译器需要知道参数的类型和大小,以便将它们正确地传递给函数。一般来说,函数参数被压入堆栈(但这不是通用规则,特别是在 64 位体系结构系统上)。考虑以下情况。如果你调用像这样的函数

foo(42);
Run Code Online (Sandbox Code Playgroud)

编译器如何知道它必须传递给函数的整数值的大小是多少?该数字42可以使用各种位宽度表示,例如 1、2、4(甚至 8)字节整数:

00101010
0000000000101010
00000000000000000000000000101010
Run Code Online (Sandbox Code Playgroud)

现在,如果函数没有签名来表明,例如,参数是 a char(1 字节)、a short(可能是 2 字节)或 aint,它可能是 4 个字节,那么编译器会无法确定正确的尺寸。这意味着,如果它将任意数量的字节推送到堆栈,但该函数需要另一个大小,则会发生堆栈损坏。

另一个很好的例子是返回结构 ( struct)。通常,原始返回值(例如整数和浮点数)在寄存器中返回;这通常是EAXx86 上的寄存器。但是如果想编写一个返回结构体的函数怎么办?如果结构体的整体大小太大以至于无法放入寄存器中,则编译器必须生成将返回值推入堆栈的代码,而不是将其分配给寄存器。所以如果一个函数定义为

int foo()
{
    return 1337;
}
Run Code Online (Sandbox Code Playgroud)

或作为

struct bar {
    int a;
    char b[16];
    float x;
};

struct bar foo()
{
    struct bar ret;
    ret.a = 0;
    memcpy(&ret.b, "abcdefghijklmno", sizeof(ret.b));
    ret.x = 3.1415927;
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

将生成不同的汇编代码(和机器代码) - 返回整数的第一个函数将使用寄存器EAX来存储返回值,但第二个调用将必须使用堆栈。