Default arguments
默认参数
允许调用函数而不提供一个或多个尾随参数。
参数列表中的参数使用下列语法指示功能声明...
attr(optional) decl-specifier-seq declarator = initializer | (1) | |
---|---|---|
attr(optional) decl-specifier-seq abstract-declarator(optional) = initializer | (2) | |
在函数调用中,使用默认参数来代替缺少的尾随参数:
二次
void point(int x = 3, int y = 4
point(1,2 // calls point(1,2)
point(1 // calls point(1,4)
point( // calls point(3,4)
二次
在函数声明中,在带有默认参数的参数之后,所有后续参数必须。
- 在本声明或先前声明中提供默认参数;或
- 是一个函数参数包。%28自C++11%29
省略号不是参数,因此可以使用默认参数跟随参数。
二次
int f(int = 1, int // error, assuming there's no previous declaration of f
int g(int n = 0, ... // ok
template<class...T> void h(int i = 0, T... args // ok
二次
的参数列表中只允许默认参数。函数声明和Lambda-表达式,自C++14%29以来,不允许在指向函数、函数引用或胡枝子f声明。模板参数列表使用类似的语法默认模板参数...
对于非模板函数,可以将默认参数添加到已声明的函数中,如果该函数在同一范围内重新声明。在函数调用的点,默认值是函数的所有可见声明中提供的默认值的结合。即使该值与%29相同,重声明也不能为默认值已可见%28的参数引入默认值。内部作用域中的重新声明不会从外部范围获取默认参数。
二次
void f(int, int // #1
void f(int, int = 7 // #2 OK: adds a default
void h() {
f(3 // #1 and #2 are in scope; makes a call to f(3,7)
void f(int =1, int // Error: inner scope declarations don't acquire defaults
}
void m() { // new scope begins
void f(int, int // inner scope declaration; has no defaults.
f(4 // Error: not enough arguments to call f(int, int)
void f(int, int = 6
f(4 // OK: calls f(4,6
void f(int, int = 6 // Error: cannot redeclare a default in the same scope
}
void f(int = 1, int // #3 OK, adds a default to #2
void n() { // new scope begins
f( // #1, #2, and #3 are in scope: calls f(1, 7
}
二次
如果内联函数在不同的翻译单元中声明,在每个翻译单元的末尾,累积的默认参数集必须相同。
如果朋友声明指定一个默认的,它必须是一个朋友函数定义,并且在翻译单元中不允许该函数的其他声明。
大使用-声明继承已知的默认参数集,如果以后向函数%27s命名空间添加更多参数,则在可见使用声明的任何地方也可以看到这些默认值。
二次
namespace N {
void f(int, int = 1
}
using N::f;
void g() {
f(7 // calls f(7, 1
f( // error
}
namespace N {
void f(int = 2, int
}
void h() {
f( // calls f(2, 1
}
二次
将查找默认参数中使用的名称,并对其进行检查。可达性,并在声明点绑定,但在函数调用点执行:
二次
int a = 1;
int f(int
int g(int x = f(a) // lookup for f finds ::f, lookup for a finds ::a
// the value of ::a, which is 1 at this point, is not used
void h()
{
a = 2; // changes the value of ::a
{
int a = 3;
g( // calls f(2), then calls g() with the result
}
}
二次
为了成员函数对于非模板类,默认参数允许在类外定义中使用,并与类主体内的声明提供的默认参数相结合。如果这些类外默认值会将成员函数转换为默认、复制或移动构造函数,则程序的格式不正确。对于类模板的成员函数,必须在成员函数的初始声明中提供所有默认值。
二次
class C {
void f(int i = 3
void g(int i, int j = 99
C(int arg // non-default constructor
};
void C::f(int i = 3) { // error: default argument already
} // specified in class scope
void C::g(int i = 88, int j) { // OK: in this translation unit,
} // C::g can be called with no argument
C::C(int arg = 1) { // Error: turns this into a default constructor
}
二次
霸王虚拟函数不会从基类声明中获取默认参数,当进行虚拟函数调用时,根据对象%28注意事项的静态类型确定默认参数:这可以通过非虚拟接口模式%29
二次
struct Base {
virtual void f(int a = 7
};
struct Derived : Base {
void f(int a) override;
};
void m() {
Derived d;
Base& b = d;
b.f( // OK: calls Derived::f(7)
d.f( // Error: no default
}
二次
默认参数中不允许局部变量,除非在未计算的上下文%28中使用,因为C++14%29:
二次
void f()
{
int n = 1;
extern void g(int x = n // error: local variable cannot be a default
extern void h(int x = sizeof n // OK as of CWG 2082
}
二次
大这默认参数中不允许指针:
二次
class A {
void f(A* p = this) { } // error: this is not allowed
};
二次
默认参数%28不允许非静态类成员,即使它们未被计算为%29,除非用于形成指向成员的指针或在成员访问表达式中。
二次
int b;
class X {
int a;
int mem1(int i = a // error: non-static member cannot be used
int mem2(int i = b // OK: lookup finds X::b, the static member
static int b;
};
二次
函数参数在默认参数%28中是不允许的,即使它们在C++14%29之前未被计算为%29%28,除非它们是自C++14%29以来未计算的%28。注意,参数列表前面出现的参数位于范围*
二次
int a;
int f(int a, int b = a // Error: the parameter a used in a default argument
int g(int a, int b = sizeof a // Error until CWG 2082
// OK after CWG 2082: use in unevaluated context is OK
二次
默认参数不是函数类型的一部分。
二次
int f(int = 0
void h() {
int j = f(1
int k = f( // calls f(0
}
int (*p1)(int) = &f;
int (*p2)() = &f; //Error: the type of f is int(int)
二次
如果Lambda表达出现在默认参数中,它不能显式或隐式地捕获任何内容。
二次
void f2() {
int i = 1;
void g1(int = ([i]{ return i; })() // error: captures something
void g2(int = ([i]{ return 0; })() // error: captures something
void g3(int = ([=]{ return i; })() // error: captures something
void g4(int = ([=]{ return 0; })() // OK: capture-less
void g5(int = ([]{ return sizeof i; })() // OK: capture-less
}
二次
运算符函数除函数调用操作符外,不应有默认参数。
二次
class C {
int operator[](int i = 0 // ill-formed
int operator()(int x = 0 // ok
};
二次
缺陷报告
以下行为更改缺陷报告追溯应用于先前发布的C++标准。
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 2082 | C++14 | default arguments were forbidden to use locals in unevaluated context | unevaluated context use allowed |
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。