我遇到了一个必须换掉某个对象的值的情况。由于我自己的草率复制和粘贴,我不小心复制了类型声明。这是一个简化的例子:
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。
答案 0 :(得分:6)
根据标准规定的规则,这个程序是完全有效和正确的,编译器不需要捕获任何东西,没有什么可以捕获的。
该标准允许相同的命名变量存在于它们各自的范围内,它清楚地定义了在特定范围内使用它们时将引用哪个变量的规则。名称变量隐藏或 shadow 全局范围内的变量。
在您的本地范围内(在条件if
块中),本地声明的i
隐藏了全局i
。如果您需要访问此范围内的全局i
,则需要使用::i
。
在条件块之外,唯一存在的i
是全局声明的i
。
在评论中回答问题:
虽然编译器实际上不必警告这一点,但是如果编译启用了最高警告级别的程序,或者您明确告诉编译器警告此特定行为,则大多数编译器将为您提供此诊断。
对于 GCC ,您可以使用-Wshadow
。
-Wshadow
每当局部变量或类型声明影响另一个变量,参数,类型或类成员(在C ++中)时,或者在内置函数被遮蔽时发出警告。请注意,在C ++中,编译器会警告局部变量是否影响显式typedef,但如果它影响struct / class / enum则不会。
答案 1 :(得分:1)