2016-05-31 106 views
1

我有点在这种情况下困惑:变量名歧义C++

#include <iostream> 

void function(int origin) 
{ 
    if (origin < 0) 
    { 
     double origin = 0.3; 

     std::cout << origin << std::endl; 
    } 
} 

int main() 
{ 
    function(-4); 
} 

它被编译并成功下V120工具集使用VS2013运行。是不是C++错了?因为做同样的事情,但只是在函数的开始,它会产生编译时错误。

+1

这不是问题,但不要使用'std :: endl',除非你需要额外的东西。 ''\ n''结束一行。 –

+1

@PeteBecker哇,来自上师的建议无法避免;)我从来没有想过** :: endl **和**'\ n'**之间有一些区别。将通过一些关于它的参考。谢谢 –

回答

1

我不介意这种C++行为。当然,它可能会导致错误/疏漏,正如你已经证明的那样。但是,你可以在C为此++

for (int i = 0; i < 4; ++i) { 
    for (int i = 0; i < 5; ++i) { 
     cout << i; 
    } 
    cout << i; 
} 
cout << endl; 
for (int i = 0; i < 4; ++i) { 
    for (int j = 0; j < 5; ++j) { 
     cout << j; 
    } 
    cout << i; 
} 

并且因为i在内部for循环的范围重新定义为一个不同的变量的结果是相同的。

在其他语言如C#中你不能这样做。它会告诉你试图在内部范围内重新声明一个同名的变量。

我觉得这种过度保护。当我用循环剪切和粘贴代码时,必须重新声明i(我们都倾向于将其用作循环变量)为i1i2等等,我总是会错过一个,使用剪切和粘贴代码,所以我在i3循环中使用arr[i],当时我的意思是arr[i3](哎呦)。

在生产代码中,我同意防御性编码意味着您应该在同一个函数中为循环变量使用不同的名称。

但是在试验时能够在嵌套for循环中重用变量名是很好的。 C++给你这个选择。

1

是不是C++错了?

不需要。重新声明标识符是完全合法的,只要它在不同的范围内即可。在这种情况下,范围是if语句的当时主体。

它并不含糊。将使用最近的前面的声明。

+1

虽然它是有效的,但它通常不被推荐,因为它可能导致错误。 – SurvivalMachine

1

不,这没有错。根据标准,这是完全有效的行为。

void function(int origin) 
{ 
    if (origin < 0) // scope of the first 'origin' 
    { 
     double origin = 0.3; // scope of the second 'origin' begins 
          // scope of the first 'origin' is interrupted 

     std::cout << origin << std::endl; 
    } //block ends, scope of the second 'origin' ends 
     //scope of the first 'origin' resumes 
} 

由于tupe_cat表示,如果它们的作用域变化,重新声明它总是有效的。在这种情况下,属于内部范围的变量将超出外部范围。

2

这根据C++标准是合法的,节3.3.3.1:

在一个块中声明的名称是局部的块;它有块范围。它的潜在范围从宣布的角度开始,到结束时结束。在块范围声明的变量是局部变量。

这样的重新声明隐藏了origin参数。

原因做同样的事情,但只是在函数的开始它会给编译时错误。

你得到一个错误,因为C++标准明确禁止这样的重复宣告第3.3.3.2:

的参数名称,不得在函数定义的最外层块,也不在最外层块中重新声明任何与函数尝试块关联的处理程序。

这种排除的原因是函数参数对函数的外部范围是局部的,所以如果重新声明没有另一个大括号,会在同一范围内引入重复标识符。