提问人:Fedor 提问时间:10/6/2021 最后编辑:Vlad from MoscowFedor 更新时间:10/7/2021 访问量:2397
函数默认参数值取决于 C++ 中的参数名称 [重复]
Function default argument value depending on argument name in C++ [duplicate]
问:
如果在 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 每次调用函数时都会计算默认参数 没有相应参数的参数。参数应 在默认值中不显示为可能计算的表达式 论点。在默认值之前声明的函数的参数 参数在作用域内,可以隐藏命名空间和类成员名称
它提供了以下示例:
int h(int a, int b = sizeof(a)); // OK, unevaluated operand
因此,此函数声明
void f(int y = sizeof(y)) {}
是正确的,因为在此表达式中,不是基于 C++17 8.3.3 Sizeof 的计算操作数:sizeof(y)
y
1 sizeof 运算符生成对象中的字节数 其操作数的表示。操作数可以是表达式、 这是未计算的操作数(第 8 条)或带括号的 类型 ID。
和 C++17 6.3.2 声明点:
1 名称的声明点紧跟在其之后 完整的声明器(第 11 条)和其初始值设定项(如果有)之前, 除非下文另有说明。
评论
代码看起来格式不正确,所以 Clang 没问题。
[基本.scope.pdecl]
1 名称的声明点紧接在其完整声明符 ([dcl.decl]) 之后和初始值设定项(如果有)之前,除非下面另有说明。
这是正在讨论的臭名昭著的段落。我把它带到这里只是为了提一下,“除非如下所述”不包括任何默认参数的提及。所以在之前声明.y
= sizeof(y)
另一个相关段落是
[dcl.fct.默认]
9 每次调用函数时,都会计算一个默认参数,而不计算相应参数的参数。参数不应在默认参数中显示为可能计算的表达式。在默认参数之前声明的函数的参数在作用域中,可以隐藏命名空间和类成员名称。
sizeof(y)
没有潜在的评估,所以这也很好。
看到第一段作为名称提供,并且它以一种不非法的方式使用,一定是 GCC 拒绝代码的一些怪癖。y
虽然就我个人而言,我不认为这是一个很大的损失。这不是最实用的代码。
评论