c++中默认参数值是怎样实现的?
author: hjjdebug
date: 2025年 05月 07日 星期三 17:51:43 CST
description: c++中默认参数值是怎样实现的?
文章目录
- 1.什么是函数参数的默认值.
- 2. 限制:
- 3. C++默认参数是怎样实现的?
1.什么是函数参数的默认值.
在函数声明中,
可以在参数列表中为某些参数指定默认值
在函数调用中,
如果用户指定了参数的值,那么就使用用户指定的值,否则就使用函数原型中定义的参数的默认值。
2. 限制:
默认参数只能从右向左定义.
原因是简化与编译器的约定,方便编译器补全缺省的值. 见最后的总结.
如果不加此限制,而是规定有默认值的优先级低,右边参数默认值优先级低于左边参数默认值优先级,
编译器也能理解用户意图,原则上也能实现.
但那就要重改编译器,且比现在的要复杂一些了,似乎也没这个必要.
3. C++默认参数是怎样实现的?
看一个简单实例:
$ cat main.cpp
#include <iostream>// 函数声明,带有默认参数
void add(int a, int b = 5) {std::cout << "Sum: " << a + b << std::endl;
}int main() {add(3); // 使用默认值:b = 5, 输出 8add(3, 10); // 不使用默认值,输出 13return 0;
}
其反汇编代码:
(gdb) disassemble/s main
Dump of assembler code for function main():
main.cpp:
8 int main() {0x000055555555521e <+0>: endbr64 0x0000555555555222 <+4>: push %rbp0x0000555555555223 <+5>: mov %rsp,%rbp9 add(3); // 使用默认值:b = 5, 输出 8
=> 0x0000555555555226 <+8>: mov $0x5,%esi // 默认值5送给了第二个参数esi0x000055555555522b <+13>: mov $0x3,%edi0x0000555555555230 <+18>: callq 0x5555555551c9 <add(int, int)>10 add(3, 10); // 不使用默认值,输出 130x0000555555555235 <+23>: mov $0xa,%esi // 调用值10送给了第二个参数esi0x000055555555523a <+28>: mov $0x3,%edi0x000055555555523f <+33>: callq 0x5555555551c9 <add(int, int)>11 return 0;0x0000555555555244 <+38>: mov $0x0,%eax12 }0x0000555555555249 <+43>: pop %rbp0x000055555555524a <+44>: retq
End of assembler dump.
我查看了一下: disassemble/s 与disassemble/m 其输出内容是一致的. 几乎没有差别.
一个修饰符是source ,一个修饰符是mix, 其实都一样的.
x86-64函数调用协议, %edi是第一参数,%esi是第2参数, 我们看到编译器把默认值5送给了第二个参数esi
它的前6个参数都是用寄存器传递,超过6个用堆栈传递.
跟gcc的约定是,当调用者参数少于函数原型个数时,从右侧开始补全,把默认值填上去.