我有一个小玩具程序:
static int value = 0;
int function(int &value=value) {
return value;
}
int main() {
function();
}
使用g++ 7.2进行编译:
测试结果显示,测试test.cc。
没问题的。
使用clang++-3.9编译:
- -test.cc----------------------------------------------------------------
test.cc:3:25: error: default argument references parameter 'value'
int function(int &value=value) {
^~~~~
test.cc:8:5: error: no matching function for call to 'function'
function();
^~~~~~~~
test.cc:3:5: note: candidate function not viable: requires single argument 'value', but no arguments were provided
int function(int &value=value) {
^
2 errors generated.
砰谁说对了
3条答案
按热度按时间iyzzxitl1#
我认为clang是正确的。从basic.scope.pdecl:
名称的声明点紧跟在其完整声明符(第dcl.decl(https://timsong-cpp.github.io/cppwp/n3337/dcl.decl)条)之后和其初始化器(如果有)之前,以下注解除外。[示例:
这里,第二个x用它自己的(不确定的)值初始化。-示例结束]
此外,从dcl.fct.default中还可以看到:
每次调用函数时都会计算默认参数。未指定函数参数的计算顺序。因此,即使未计算函数的参数,也不应在默认参数中使用这些参数。在默认参数之前声明的函数参数在作用域中,并且可以隐藏命名空间和类成员名称
k2fxgqgv2#
由于OP将问题标记为c++11,我检查了该版本的标准,并在[basic.lookup.unqual]子条款11中明确指出:
在查找用作函数参数声明子句中的默认参数(8.3.6)或用于构造函数的mem-initializer的表达式(12.6.2)的名称期间,函数参数名称是可见的,并隐藏在包含函数声明的块、类或命名空间范围中声明的实体的名称。
因此,金属撞击声是正确的。
rryofs0p3#
这里Clang是正确的。首先,function's parameter scope定义为:
函数参数(包括出现在lambda声明符中的参数)或函数局部预定义变量([dcl.fct.def])具有函数参数作用域。函数参数或函数局部预定义变量的潜在作用域从其声明点开始。
并且声明点定义为
名称的声明点紧跟在其完整声明符之后和初始化器(如果有)之前,除非下面注明。[例如:
这里,第二个x用它自己的(不确定的)值初始化。-示例结束]
因此,
value
应该是您刚刚声明的value
,而不是全局空间中的那个