使用默认参数消除函数的歧义

disambiguate function with default parameter

本文关键字:函数 歧义 默认 参数      更新时间:2023-10-16

我一直认为默认参数是重载的语法糖。
但似乎它们只是粘在一个函数(类型)的顶部——没有提供任何函数(类型)的函数。
有没有充分的理由会这样?

void foo(int i);// void (*)(int)
void foo();// void (*)()
void bar(int i = false);// void (*)(int)
int main() {
    return static_cast<void(*)()>(&foo) // works
        && static_cast<void(*)()>(&bar);// doesn’t work
}

他们肯定受到不同的对待。

void foo(int i);// void (*)(int)
void foo();// void (*)()

这些调用在链接时解析,链接器会将它们链接到不同的函数,因为它们是不同的函数。

void bar(int i = false);// void (*)(int)

它在编译时解决,如果您不提供参数,编译器将添加额外的参数,并且所有调用都将链接到同一函数。

由于是编译器添加额外的参数,因此编译器必须知道默认参数,因此它在编译时必须可见。

示例代码:

% cat t.cpp
void foo(int i);// void (*)(int)
void foo();// void (*)()
void bar(int i = false);// void (*)(int)
int main() {
    foo(0);
    foo();
    bar(0);
    bar();
}

编译结果:

% objdump -C -r t.o
t.o:     file format elf64-x86-64
RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE 
000000000000000a R_X86_64_PC32     foo(int)-0x0000000000000004
000000000000000f R_X86_64_PC32     foo()-0x0000000000000004
0000000000000019 R_X86_64_PC32     bar(int)-0x0000000000000004
0000000000000023 R_X86_64_PC32     bar(int)-0x0000000000000004

RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE 
0000000000000020 R_X86_64_PC32     .text

有 foo() 和 foo(int),但只有 bar(int) 没有 bar()。