C ++在子范围中重新声明变量不应该导致编译错误吗?

时间:2013-03-27 13:09:50

标签: c++ visual-studio-2010

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

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。

2 个答案:

答案 0 :(得分:6)

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

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

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

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


在评论中回答问题:

虽然编译器实际上不必警告这一点,但是如果编译启用了最高警告级别的程序,或者您明确告诉编译器警告此特定行为,则大多数编译器将为您提供此诊断。

对于 GCC ,您可以使用-Wshadow

  

-Wshadow

     

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

答案 1 :(得分:1)

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

如果您想使用i顶级main()使用::i

有关教程,请参阅here