首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Default arguments

允许调用函数而不提供一个或多个尾随参数。

参数列表中的参数使用下列语法指示功能声明...

attr(optional) decl-specifier-seq declarator = initializer

(1)

?

attr(optional) decl-specifier-seq abstract-declarator(optional) = initializer

(2)

?

在函数调用中,使用默认参数来代替缺少的尾随参数:

二次

代码语言:javascript
复制
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

省略号不是参数,因此可以使用默认参数跟随参数。

二次

代码语言:javascript
复制
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的参数引入默认值。内部作用域中的重新声明不会从外部范围获取默认参数。

二次

代码语言:javascript
复制
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命名空间添加更多参数,则在可见使用声明的任何地方也可以看到这些默认值。

二次

代码语言:javascript
复制
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);
}

二次

将查找默认参数中使用的名称,并对其进行检查。可达性,并在声明点绑定,但在函数调用点执行:

二次

代码语言:javascript
复制
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
  }
}

二次

为了成员函数对于非模板类,默认参数允许在类外定义中使用,并与类主体内的声明提供的默认参数相结合。如果这些类外默认值会将成员函数转换为默认、复制或移动构造函数,则程序的格式不正确。对于类模板的成员函数,必须在成员函数的初始声明中提供所有默认值。

二次

代码语言:javascript
复制
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

二次

代码语言:javascript
复制
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:

二次

代码语言:javascript
复制
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
}

二次

大这默认参数中不允许指针:

二次

代码语言:javascript
复制
class A {
  void f(A* p = this) { } // error: this is not allowed
};

二次

默认参数%28不允许非静态类成员,即使它们未被计算为%29,除非用于形成指向成员的指针或在成员访问表达式中。

二次

代码语言:javascript
复制
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。注意,参数列表前面出现的参数位于范围*

二次

代码语言:javascript
复制
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

二次

默认参数不是函数类型的一部分。

二次

代码语言:javascript
复制
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表达出现在默认参数中,它不能显式或隐式地捕获任何内容。

二次

代码语言:javascript
复制
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
}

二次

运算符函数除函数调用操作符外,不应有默认参数。

二次

代码语言:javascript
复制
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

代码语言:txt
复制
 ? cppreference.com

在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com