默认实参

来自cppreference.com


 
 
C++ 语言
 
 

允许调用函数时不提供一个或多个尾部的实参。

通过使用下列语法来为函数声明形参列表 中的形参指定默认实参。

属性 (可选) 声明说明符序列 声明符 = 初始化器 (1)
属性 (可选) 声明说明符序列 抽象声明符 (可选) = 初始化器 (2)

默认实参用来取代函数调用中缺失的尾部实参:

void point(int x = 3, int y = 4);

point(1, 2); // 调用 point(1, 2)
point(1);    // 调用 point(1, 4)
point();     // 调用 point(3, 4)

在函数声明中,所有在拥有默认实参的形参之后的形参必须:

  • 拥有在这个或同一作用域中先前的声明中所提供的默认实参:
int x(int = 1, int); // 错误:只有尾随实参能拥有默认值(假设前面没有 “x” 的声明)

void f(int n, int k = 1);
void f(int n = 0, int k); // OK:同一作用域中之前的声明为 “k” 提供了默认实参

void g(int, int = 7);

void h()
{
    void g(int = 1, int); // 错误:不在同一作用域
}
  • ...除非该形参是从某个形参包展开得到的:
template<class... T>
struct C { void f(int n = 0, T...); };

C<int> c; // OK;实例化了声明 void C::f(int n = 0, int)
  • 或者是函数形参包:
template<class... T>
void h(int i = 0, T... args); // OK
(C++11 起)

省略号不是形参,所以它可以跟在带有默认实参的形参之后:

int g(int n = 0, ...); // OK

默认实参只能在函数声明lambda 表达式(C++11 起)的形参列表中出现,而不能在函数指针、到函数的引用,或在 typedef 声明中出现。模板形参列表为它的默认模板实参使用了类似的语法。

对于非模板函数,当在同一作用域中重声明函数时,可以向已声明的函数添加默认实参。在函数调用点,可用的默认实参是由该函数所有可见的声明中所提供的默认实参的并集。重声明不能为已有可见默认值的实参引入默认值(即使值相同)。内层作用域中的重声明不从外层作用域获得默认实参。

void f(int, int);     // #1 
void f(int, int = 7); // #2 OK:添加默认实参

void h()
{
    f(3); // #1 和 #2 在作用域中;进行对 f(3, 7) 的调用
    void f(int = 1, int); // 错误:内层作用域声明不会从外层作用域获得默认实参
}

void m()
{ // 新作用域开始
    void f(int, int); // 内层作用域声明;无默认实参。
    f(4); // 错误:调用 f(int, int) 的实参不足
    void