为什么允许这些默认参数?

Kar*_*ath 5 c++ default-arguments

我发现了这个问题,我完全感到困惑.

答案说b无效,"非静态成员不能用作默认参数." 这很有道理.

我不明白的是为什么其他两个都没问题.事实上,如果默认值不是常量表达式,我很难理解语义是什么......

这里发生了什么?在编译时清楚地评估默认参数.编译器只是选择当前值吗?

#include <iostream>

int g_x = 44; 

struct Foo 
{ 
  int m_x; 
  static int s_x; 

  Foo(int x) : m_x(x) {} 
  int a(int x = g_x) { return x + 1; } 
  int b(int x = m_x) { return x + 1; }
  int c(int x = s_x) { return x + 1; }
}; 

int Foo::s_x = 22; 

int main(int argc, char** argv) 
{ 
  Foo f(6); 

  std::cout << f.a() << std::endl; 
  std::cout << f.b() << std::endl; 
  std::cout << f.c() << std::endl; 

  return 0; 
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*our 8

实际上,在调用函数时会计算默认参数,这就是为什么这是可以的.从草案C++标准部分8.3.6 默认参数说明(强调我的前进):

每次调用函数时都会计算默认参数.函数参数的评估顺序未指定.因此,函数的参数不应在默认参数中使用,即使它们未被评估.在默认参数之前声明的函数的参数在范围内,并且可以隐藏命名空间和类成员名称.

以下来自同一部分的示例为我们提供了一个理由,说明为什么我们可以使用静态成员而不是非静态成员:

[示例:以下示例中的X :: mem1()声明格式错误,因为没有为用作初始值设定项的非静态成员X :: a提供对象.

int b;
class X {
    int a;
    int mem1(int i = a); // error: non-static member a
                         // used as default argument
    int mem2(int i = b); // OK; use X::b
    static int b;
};
Run Code Online (Sandbox Code Playgroud)

但是,X :: mem2()的声明是有意义的,因为访问静态成员X :: b不需要任何对象.类,对象和成员在第9章中描述.-结束示例]


Mik*_*our 7

在编译时不会计算默认参数.每次函数调用需要它们时都会对它们进行评估.它们可以是在函数声明的上下文中有效且具有合适类型的任何表达式,除了它不能使用任何其他参数(包括this,在成员函数的情况下).

这种限制是因为未指定评估顺序,因此如果需要评估另一个参数,则无法确保参数值可用.