2

我遇到了一个必须交换某个对象的值的情况。由于我自己草率的复制和粘贴,我不小心也复制了类型声明。这是一个简化的示例:

int main()
{
    int i = 42;
    cout << "i = " << i++ << endl;

    // ... much later

    if( isSwapRequired == true )
    {
        int i = 24;
        cout << "i = " << i++ << endl;
    }
    cout << "i = " << i++ << endl;
}

令我沮丧的是,编译器没有捕捉到这一点,而是继续让它i = 24生活在自己的小范围内。后来,事实证明,在范围之外,i仍然是43. 我注意到如果两者i处于同一级别,那么编译器会很乐意地捕捉到这个错误。编译器是否有理由以不同的方式处理多个声明?

如果重要的话,我正在使用 VS10。

4

2 回答 2

8

根据标准规定的规则,这个程序是完全有效和正确的,编译器不需要捕获任何东西,没有什么可以捕获的。

该标准允许相同的命名变量存在于它们各自的范围内,并且明确定义了在特定范围内使用它们时将引用哪个变量的规则。相同命名的变量在全局范围内隐藏隐藏变量。

在您的本地范围内(在条件if内),本地声明i的隐藏了全局i。如果您需要在此范围内访问全局i,则需要使用::i.

在条件块之外,唯一i存在的是全局声明的i.


在评论中回答问题:

尽管编译器实际上不必对此发出警告,但如果您在启用最高警告级别的情况下编译程序或明确告诉编译器警告此特定行为,大多数编译器都会为您提供此诊断。

对于GCC,您可以使用-Wshadow.

-W阴影

每当局部变量或类型声明遮蔽另一个变量、参数、类型或类成员(在 C++ 中),或者当一个内置函数被遮蔽时发出警告。请注意,在 C++ 中,如果局部变量隐藏了显式 typedef,编译器会发出警告,但如果它隐藏了 struct/class/enum,则不会发出警告。

于 2013-03-27T13:11:40.753 回答
1

这不是多重声明,因为您的每个is 都有不同的范围,并且本地范围始终支持全局范围。

如果你想i从顶层使用你的main()use ::i

请参阅此处获取教程。

于 2013-03-27T13:12:00.910 回答