跳至主要內容

默认参数

张威大约 5 分钟c/c++c++基础

默认参数

1681304023862-96f676ac-4269-4aa5-bf35-9cf222f1743c
1681304023862-96f676ac-4269-4aa5-bf35-9cf222f1743c

默认参数的目的

C++可以给函数定义默认参数值。通常,调用函数时,要为函数的每个参数给定对应的实参

void func1(int x, int y);
void func1(int x, int y)
{
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
}

无论何时调用func1函数,都必须要给其传递两个参数。但C++可以给参数定义默认值,如果将func1函数参数中的x定义成默认值0, y定义成默认值0,只需简单的将函数声明改成

void func1(int x = 0, int y = 0);

这样调用时,若不给参数传递实参,则func1函数会按指定的默认值进行工作。允许函数设置默认参数值,是为了让编程简单,让编译器做更多的检查错误工作。

调用效率问题(汇编)

若两个函数都传入,会提高效率,形参带默认值的函数;若传入,则效率不变。

int main() {
  int a = 10;
  int b = 20;

  int ret = sum(a, b);
  /*
  mov eax, dword ptr[ebp-8]
  push eax
  mov ecx, dword ptr[ebp-4]
  push ecx
  call sum
  */

  ret = sum(a); 
  /*
  push 14H // 这里直接push省去mov
  mov ecx, dword ptr[ebp-4]
  push ecx
  call sum
  */ 
	
  //如果实参是立即数,则效率和默认参数是一样的
  ret = sum();
  ret = sum(30, 40);	
  /*
  push 28H	//40
  push 1EH	//30
  call sum
  */
    
  return 0;
}

int sum(int a = 10, int b = 20) {
    return a + b;
}
  • 当调用次数大的时候开销差别还是很可观

默认参数的声明

若在定义时而不是在声明时置默认值,那么函数定义一定要在函数的调用之前。因为声明时已经给编译器一个该函数的向导,所以只在定义时设默认值时,编译器只有检查到定义时才知道函数使用了默认值。若先调用后定义,在调用时编译器并不知道哪个参数设了默认值。所以我们通常是将默认值的设置放在声明中而不是定义中。

默认值只能给一次
默认值只能给一次
/*error
int sum(int a = 10, int b);	//error,默认值顺序从右往左赋值
int sum(int a, int b = 20);
*/

//下面的这种情况编译正常,原因:执行2的时已经知道了1给b赋了默认值(声明可以多次)
int sum(int a, int b = 20);	//1	
int sum(int a = 10, int b);	//2

默认参数的顺序规定

如果一个函数中有多个默认参数,则形参分布中,默认参数应从右至左逐渐定义,因为涉及到参数的入栈出栈。当调用函数时,只能向左匹配参数。如:

void func2(int a = 1, int b, int c = 0, int d);//error
void func2(int a, int b, int c = 0, int d = 0);//ok

若给某一参数设置了默认值,那么在参数表中其后所有的参数都必须也设置默认值,否则,由于函数调用时可不列出已设置默认值的参数,编译器无法判断在调用时是否有参数遗漏。

默认参数与函数重载

默认参数可将一系列简单的重载函数合成为一个。例如:

void func3();
void func3(int x);
void func3(int x, int y);
//上面三个函数可以合成下面这一个
void func3(int x = 0, int y = 0);

如果一组重载函数(可能带有默认参数)都允许相同实参个数的调用,将会引起调用的二义性

void func4(int);
void func4(int x, int y = 0);
void func4(int x = 0, int y = 0);

所以在

课堂代码

#include <iostream>

using std::cout;
using std::endl;
#if 0
int add(){ return 1; }
int add(int x) { return x + 0 + 1; }
int add(int x,int y) { return x + y + 1; }
int add(int x,int y, int z) { return x + y + z; }
#endif
#if 0
//二义性
int add(int x, int y)
{
    return x + y;
}
#endif
//默认参数要从右往左进行连续的赋初值
int add(int x = 0, int y = 0, int z = 0)
{
    return x + y + z;
}

int main(int argc, char **argv)
{
    int a = 3, b = 4, c = 5;
    cout << "add(a, b, c) = " << add(a, b, c) << endl;
    cout << "add(a, b) = " << add(a, b) << endl;//二义性
    cout << "add(a) = " << add(a) << endl;
    cout << "add() = " << add() << endl;
    return 0;
}