在封闭范围内重新声明变量是未定义的行为吗?

时间:2018-10-16 19:43:40

标签: c++ undefined-behavior

#include <iostream>
using namespace std;

int main() {
    int i = 0;
    if(true) {
        int i = 5;
        cout << i << '\n';
    }
    return 0;
}

尝试在Ideone上运行以上代码以查看其是否合法。结果让我感到困惑:

  • 我们遇到了编译错误(1)(2)
  • 或者此代码按预期的(1)打印5
  • 或者它什么也不打印(1)(2)

从我的链接中可以看到,每次在Ideone上进行编译时,同一代码的行为都将完全不同!这闻起来像是未定义的行为(UB)。

OK C ++以其非直观的行为而闻名! -我承认这只是我的直觉,但是我什至不希望C ++在内部作用域UB中重新声明变量!我希望阴影或强制编译错误。

我的代码真的是根据C ++标准编写的UB吗,还是仅仅是Ideone和/或gcc的独特之处?如果是UB,是因为我重新声明了i还是其他原因导致我现在没注意到的UB?

2 个答案:

答案 0 :(得分:7)

  

在封闭范围内重新声明变量是UB吗?

不,不是。

您看到的编译器错误很可能是由于声明了外部from PyQt5 import QtCore, QtWidgets, uic class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) uic.loadUi("ui_mainwindow.ui",self) shorcut = QtWidgets.QShortcut(QtCore.Qt.Key_Return, self.myTreeWidget, context=QtCore.Qt.WidgetShortcut, activated=self.some_function) def some_function(self): print("some_function") if __name__ == '__main__': import sys app = QtWidgets.QApplication(sys.argv) w = MainWindow() w.show() sys.exit(app.exec_()) 但未使用它而引起的。

否则,您的代码就可以了。

它在https://ideone.com/AwVJqZ和桌面上都可以正常工作。

答案 1 :(得分:2)

没有未定义的行为,该标准允许名称隐藏,该内容已在[basic.scope.hiding]中涵盖:

  

在嵌套的声明性区域中声明名称会在封闭的声明性区域中隐藏相同名称的声明;参见[basic.scope.declarative]和[basic.lookup.unqual]。

[basic.scope.declarative]说:

  

每个名称都会在程序文本的某些部分(称为声明性区域)中引入,这是该名称有效的程序的最大部分,也就是说,该名称可以用作不合格名称来引用同一实体。   通常,每个特定名称仅在程序文本的某些可能不连续的部分(称为范围)内有效。   要确定声明的范围,有时可以方便地引用声明的潜在范围。   声明的范围与其潜在范围相同,除非潜在范围包含另一个同名声明。   在那种情况下,内部(包含)声明区域中声明的潜在范围被排除在外部(包含)声明区域中声明的范围之外。

并给出以下示例:

  

[示例:在

int j = 24;
int main() {
  int i = j, j;
  j = 42;
}
     

将标识符j声明为名称两次(并使用两次)。的   第一个j的声明性区域包括整个示例。的   第一个j的潜在范围在该j和之后立即开始   扩展到程序的末尾,但其(实际)范围不包括   ,和}之间的文本。第二个的声明性区域   j的声明(分号前的j)包括所有   {和}之间的文本,但其潜在范围不包括   我的声明j的第二个声明的范围相同   作为其潜在范围。 —示例example]

我不知道为什么您会从IDEone中看到这样的可变结果。它没有提供很多旋钮来弄清楚发生了什么。 Wandbox是提供许多旋钮且在这种情况下不具有相同可变性的几种选择之一。