函数参数默认值(缺省函数)
函数参数在有默认值时,如果调用时没有传参,则默认push默认值。
实例一:不带默认值
#include <iostream>
using namespace std;
int fun(int a, int b, int c);
int main()
{
fun(10, 20, 30); //若有默认值,且调用时未传参,则push 默认值
/*
push 30 //
push 20
push 10
call fun()
add esp,0ch
*/
return 0;
}
int fun(int a, int b, int c)
{
/*
push abp
mov ebp,esp
sub esp,Occh
……
*/
cout << a << '\n' << b << '\n' << c << endl;
return 0;
/*
mov eax,0
*/
}
实例二:函数声明与定义冲突
函数的默认值在声明时,同一个参数不能重复赋值。如以下实例:
int fun1(int a, int b, int c = 100);//定义时 c = 100,
int main()
{
fun1(10, 20, 30); //error 重定义默认参数: 参数 1
return 0;
}
int fun1(int a, int b, int c = 100)// c = 100 缺省参数重定义
{
cout << a << '\n' << b << '\n' << c << endl;
return 0;
}
在例中,参数 c
进行了重复赋值,编译器在编译时给出报错信息为:“重定义默认参数: 参数 1”。
原因分析:函数的声明和定义都会产生函数符号,且函数符号相同。在进行默认参数赋值时,声明点和定义点的参数列表中的参数只需要(且只能)赋值一次,因为如果两次赋值的值不同,编译器就无法判断该使用哪一个值作为默认值使用。
实例三:声明点和定义点同时赋值
函数的默认参数只支持调用方(main)可见的参数列表中的参数,如:本例中在主函数之上声明或定义的fun2()
#include <iostream>
using namespace std;
int fun2(int a, int b, int c = 100);//定义时 b = 100,支持缺省一位参数
int main()
{
fun2(10, 20, 30);
fun2(10, 20);
//fun2(10);// error 函数不接受 1 个参数
/*
错误原因:程序顺序执行,在调用时只能看见该函数之前的声明。因此,在
函数定义点中的"b=100",处的默认参数无效。
*/
return 0;
}
int fun2(int a, int b = 100, int c)//编译通过,但 b 的默认赋值无用
{
cout << a << '\n' << b << '\n' << c << endl;
return 0;
}
实例四:多个声明中连续赋值
函数的声明可以有多个,可以在声明中遵循从右向左连续赋值。如下实例:
#include <iostream>
using namespace std;
int fun3(int a, int b, int c = 100);
int fun3(int a, int b = 100, int c);
int main()
{
fun3(10, 20, 30);
fun3(10, 20); // 10 20 100
fun3(10); // 10 100 100
return 0;
}
int fun3(int a, int b, int c)
{
cout << a << '\n' << b << '\n' << c << endl;
return 0;
}
注:
需要注意的是,实例二在调用点是已传入实参,且传入的实参(缺省参数)在跳转到函数主体时发现与函数主体中的缺省参数存在重复定义,从而引发报错。
而实例三中,在调用点传参时参照fun3()的声明,只有一个缺省参数,并且在传参后跳转到函数主体的过程中没有发现同一个缺省参数的重定义,因此实例三没有报错,但也因此实例三在函数主体中的缺省参数失效(如果传入参数,使用传入的参数,否则使用默认缺省值)。