c++ - 在子语句的最外层 block 中重新声明的变量

标签 c++ language-lawyer

#include <iostream>
int main(){
  int b = 2;
  if(int a = 0){  // #condition
  }else if(b == 2){
    int a;  //#1
  }
}
上面的代码可以是compiled在 gcc 和 clang 中。但是,根据相关规则的说法,这段代码应该是格式错误的。规则是:
stmt.stmt#3

A name introduced by a declaration in a condition (either introduced by the decl-specifier-seq or the declarator of the condition) is in scope from its point of declaration until the end of the substatements controlled by the condition. If the name is redeclared in the outermost block of a substatement controlled by the condition, the declaration that redeclares the name is ill-formed.


不是在 else 后面的 if 语句吗?不是由条件控制的子语句? (即,只有 #condition 处的条件被执行为 false 才会执行 else 之后的 if 语句)。那么,为什么在这种子语句的最外层块中重新声明名称的声明可以被视为格式良好的代码?
也许在版本 n4659 的规则中对短语“由条件控制的子语句”存在一些争论。不过,这样的想法在最新的草案中显然是清晰的。
stmt.stmt#stmt.pre-2

A substatement of a statement is one of the following:
for a selection-statement, any of its statements (but not its init-statement)


这意味着 else 之后的语句是主 if-statement 的子语句,那么接下来的规则说:
stmt.stmt#stmt.pre-5

A name introduced in a selection-statement or iteration-statement outside of any substatement is in scope from its point of declaration until the end of the statement's substatements. Such a name cannot be redeclared in the outermost block of any of the substatements


该规则显然表明,我们不能重新声明与这些子语句最外层块中的条件声明相同的名称。那么,我很好奇是我误解了这些规则还是草案中存在一些缺陷?

最佳答案

不。
你错过了 else 引入的块作用域子语句:

[stmt.selected.general/2]: The substatement in a selection-statement (each substatement, in the else form of the if statement) implicitly defines a block scope ([basic.scope]). If the substatement in a selection-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original substatement. [..]


即你的代码真的是:
#include <iostream>

int main()
{
  int b = 2;
  if (int a = 0) {
  }
  else {
    if (b == 2) {
       int a;
    }
  }
}
因此,您正在查看的块(由嵌套 if 引入的块)不是所讨论的“最外层”块。所以,虽然 a在该块的范围内,它可以被隐藏。
这确实意味着 you can't declare an a inside a "naked" else ,即以下格式不正确:
#include <iostream>

int main()
{
  int b = 2;
  if (int a = 0) {
  }
  else {
    int a;
  }
}

/*
prog.cpp: In function ‘int main()’:
prog.cpp:9:9: error: redeclaration of ‘int a’
     int a;
         ^
prog.cpp:6:11: note: ‘int a’ previously declared here
   if (int a = 0) {
*/

关于c++ - 在子语句的最外层 block 中重新声明的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64707811/

相关文章:

c - 为什么 C 编译器允许从 uint16_t 静默转换为枚举类型?

c++ - 在关于数据库和 GUI 的模型代码中使用枚举时减少代码重复

c++ - 在另一个 vector 包含的 vector 中创建一个对象

c++ - SQLDataBase setDatabaseName 在 QT 中不起作用

c++ set<> 类对象。使用自己的比较器给出错误 : C2804: binary 'operator <' has too many parameters

c++ - NaN 上的飞船运算符(operator)

c++ - 函数模板参数推导是否应该考虑转换运算符?

c++ - cmake格式化字符串输出

c++ - 条件运算符的值类别

list - 为什么可以在准引用列表末尾的非列表上使用取消引用拼接?