为什么在 if 语句中声明的变量仍在 else 块的范围内?
Why is variable declared in an if-statement still in scope in else block?
考虑这段代码:
if (int* p = nullptr) {
}
else {
std::cout << *p << std::endl;
}
使用 clang 7.0.1 使用 -std=c++17
、-Wall
、-Wextra
和 -pedantic-errors
编译,没有生成任何警告。
我有两个问题:
这怎么可能?我一直认为这些变量的范围以 if 块结束。如果可能的话,我会感谢标准的报价。
如果它是合法的,它不应该至少产生一个警告吗?这个功能有什么合理的应用吗?
Why is variable declared in an if-statement still in scope in else block?
因为标准是这样说的。这么设计大概是因为有用吧
- How is this possible?
不清楚为什么不可能。
I always thought that scope of such variables ends with the if-block.
你假设错误。
I'd be thankful for quotation from the standard if possible. [language-lawyer]
最新草稿说:
[stmt.select.general]
Selection statements choose one of several flows of control.
selection-statement:
- ...
- if constexpropt ( init-statementopt condition ) statement else statement
- ...
请注意,整个 if (condition) statement else statement
是一个选择语句。
[basic.scope.block]
Each
- selection or iteration statement ([stmt.select], [stmt.iter]),
- ...
introduces a block scope that includes that statement or handler.
请注意,条件 直接在 if 语句中而不是在子语句中,因此其中的声明会延伸到整个块范围的末尾,其中包含 if 子语句和 else 子语句(这些子语句不是标准名称)。
还有一个非常清楚的例子演示了格式错误的重新声明,并顺便显示了此类声明的范围:
if (int x = f()) {
int x; // error: redeclaration of x
}
else {
int x; // error: redeclaration of x
}
- If it's legal though, shouldn't it at least generate a warning?
是的,如果编译器能够在编译时检测到所有可证明的空指针间接寻址,那就太好了。可能值得提交有关此极端情况的功能请求。
Are there any reasonable applications of such feature?
当然可以。以下捏造的例子对我来说似乎是合理的:
if (Response r = do_request()) {
log << "great success. content: " << r.content;
} else {
log << "someone broke it :( error: " << r.error_code;
}
或者如果您不喜欢隐式转换:
if (Response r = do_request(); r.is_success()) {
考虑这段代码:
if (int* p = nullptr) {
}
else {
std::cout << *p << std::endl;
}
使用 clang 7.0.1 使用 -std=c++17
、-Wall
、-Wextra
和 -pedantic-errors
编译,没有生成任何警告。
我有两个问题:
这怎么可能?我一直认为这些变量的范围以 if 块结束。如果可能的话,我会感谢标准的报价。
如果它是合法的,它不应该至少产生一个警告吗?这个功能有什么合理的应用吗?
Why is variable declared in an if-statement still in scope in else block?
因为标准是这样说的。这么设计大概是因为有用吧
- How is this possible?
不清楚为什么不可能。
I always thought that scope of such variables ends with the if-block.
你假设错误。
I'd be thankful for quotation from the standard if possible. [language-lawyer]
最新草稿说:
[stmt.select.general]
Selection statements choose one of several flows of control. selection-statement:
- ...
- if constexpropt ( init-statementopt condition ) statement else statement
- ...
请注意,整个 if (condition) statement else statement
是一个选择语句。
[basic.scope.block]
Each
- selection or iteration statement ([stmt.select], [stmt.iter]),
- ...
introduces a block scope that includes that statement or handler.
请注意,条件 直接在 if 语句中而不是在子语句中,因此其中的声明会延伸到整个块范围的末尾,其中包含 if 子语句和 else 子语句(这些子语句不是标准名称)。
还有一个非常清楚的例子演示了格式错误的重新声明,并顺便显示了此类声明的范围:
if (int x = f()) { int x; // error: redeclaration of x } else { int x; // error: redeclaration of x }
- If it's legal though, shouldn't it at least generate a warning?
是的,如果编译器能够在编译时检测到所有可证明的空指针间接寻址,那就太好了。可能值得提交有关此极端情况的功能请求。
Are there any reasonable applications of such feature?
当然可以。以下捏造的例子对我来说似乎是合理的:
if (Response r = do_request()) {
log << "great success. content: " << r.content;
} else {
log << "someone broke it :( error: " << r.error_code;
}
或者如果您不喜欢隐式转换:
if (Response r = do_request(); r.is_success()) {