函数默认参数值取决于 C++ 中的参数名称

Function default argument value depending on argument name in C++

如果在C++中定义了一个新的变量,那么在初始化表达式中可以使用变量名,例如:

int x = sizeof(x);

那么函数参数的默认值呢?是否允许在那里通过名称引用参数?例如:

void f(int y = sizeof(y)) {}

此函数在 Clang 中被接受,但在 GCC 中被拒绝并出现错误:

'y' was not declared in this scope

演示:https://gcc.godbolt.org/z/YsvYnhjTb

这里是哪个编译器?

根据 C++17 标准(11.3.6 默认参数)

9 A default argument is evaluated each time the function is called with no argument for the corresponding parameter. A parameter shall not appear as a potentially-evaluated expression in a default argument. Parameters of a function declared before a default argument are in scope and can hide namespace and class member name

它提供了以下示例:

int h(int a, int b = sizeof(a)); // OK, unevaluated operand

所以,这个函数声明

void f(int y = sizeof(y)) {}

是正确的,因为在此表达式 sizeof(y) 中,y 不是计算的操作数,基于 C++17 8.3.3 Sizeof:

1 The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is an unevaluated operand (Clause 8), or a parenthesized type-id.

和C++17 6.3.2声明点:

1 The point of declaration for a name is immediately after its complete declarator (Clause 11) and before its initializer (if any), except as noted below.

代码没有出现格式错误,因此 Clang 没问题。

[basic.scope.pdecl]

1 The point of declaration for a name is immediately after its complete declarator ([dcl.decl]) and before its initializer (if any), except as noted below.

这是正在讨论的臭名昭著的段落。我把它带到这里只是为了提到“除了下面提到的”不包括任何默认参数的提及。所以 y 是在 = sizeof(y).

之前声明的

另一个相关段落是

[dcl.fct.default]

9 A default argument is evaluated each time the function is called with no argument for the corresponding parameter. A parameter shall not appear as a potentially-evaluated expression in a default argument. Parameters of a function declared before a default argument are in scope and can hide namespace and class member names.

sizeof(y) 没有潜在的评估,所以这也很好。

鉴于第一段使 y 可用作名称,并且其使用方式并非非法,因此一定是 GCC 的某些怪癖拒绝了该代码。

虽然就我个人而言,我并不认为这是一个很大的损失。这不是最实用的代码。