C ++中的变量名称歧义
Variables names ambiguity in C++
我对这种情况有点困惑:
#include <iostream>
void function(int origin)
{
if (origin < 0)
{
double origin = 0.3;
std::cout << origin << std::endl;
}
}
int main()
{
function(-4);
}
在 v120 ToolSet 下使用 VS2013 成功编译并运行。是不是C++错了?因为做同样的事情,但只是在函数的开头,它会产生编译时错误。
Isn't it wrong C++?
没有。重新声明一个标识符是完全合法的,只要它在不同的范围内。在这种情况下,范围是 if 语句的 then-body。
没有歧义。将使用最近的先前声明。
不,没有错。根据标准,这是完全有效的行为。
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所说,如果范围不同,重新声明总是有效的。在这种情况下,属于内部范围的变量将超过外部范围。
根据 C++ 标准第 3.3.3.1 节,这是合法的:
A name declared in a block is local to that block; it has block scope. Its potential scope begins at its point of declaration and ends at the end of its block. A variable declared at block scope is a local variable.
这种重新声明隐藏了 origin
参数。
Cause doing the same but just in the beginning of function it gives a compile-time error.
您收到错误消息,因为 C++ 标准在第 3.3.3.2 节中明确禁止此类重新声明:
A parameter name shall not be redeclared in the outermost block of the function definition nor in the outermost block of any handler associated with a function-try-block.
这种排除的原因是函数参数在函数的外部范围内是局部的,因此在没有另一层大括号的情况下进行重新声明会将重复的标识符引入同一范围。
我不介意这种 C++ 行为。当然,正如您所展示的那样,它可以导致 bugs/oversights 。但是你可以用 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
(我们都倾向于将其用作循环变量)为 i1
、i2
等,这很烦人。我总是错过一个,用剪切和粘贴代码,所以我在 i3
循环中使用 arr[i]
,而我的意思是 arr[i3]
(糟糕)。
在生产代码中,我同意防御性编码意味着您应该在同一函数中为循环变量使用不同的名称。
但是在进行试验时能够在嵌套的 for 循环中重用变量名真是太好了。 C++ 给了你这样的选择。
我对这种情况有点困惑:
#include <iostream>
void function(int origin)
{
if (origin < 0)
{
double origin = 0.3;
std::cout << origin << std::endl;
}
}
int main()
{
function(-4);
}
在 v120 ToolSet 下使用 VS2013 成功编译并运行。是不是C++错了?因为做同样的事情,但只是在函数的开头,它会产生编译时错误。
Isn't it wrong C++?
没有。重新声明一个标识符是完全合法的,只要它在不同的范围内。在这种情况下,范围是 if 语句的 then-body。
没有歧义。将使用最近的先前声明。
不,没有错。根据标准,这是完全有效的行为。
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所说,如果范围不同,重新声明总是有效的。在这种情况下,属于内部范围的变量将超过外部范围。
根据 C++ 标准第 3.3.3.1 节,这是合法的:
A name declared in a block is local to that block; it has block scope. Its potential scope begins at its point of declaration and ends at the end of its block. A variable declared at block scope is a local variable.
这种重新声明隐藏了 origin
参数。
Cause doing the same but just in the beginning of function it gives a compile-time error.
您收到错误消息,因为 C++ 标准在第 3.3.3.2 节中明确禁止此类重新声明:
A parameter name shall not be redeclared in the outermost block of the function definition nor in the outermost block of any handler associated with a function-try-block.
这种排除的原因是函数参数在函数的外部范围内是局部的,因此在没有另一层大括号的情况下进行重新声明会将重复的标识符引入同一范围。
我不介意这种 C++ 行为。当然,正如您所展示的那样,它可以导致 bugs/oversights 。但是你可以用 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
(我们都倾向于将其用作循环变量)为 i1
、i2
等,这很烦人。我总是错过一个,用剪切和粘贴代码,所以我在 i3
循环中使用 arr[i]
,而我的意思是 arr[i3]
(糟糕)。
在生产代码中,我同意防御性编码意味着您应该在同一函数中为循环变量使用不同的名称。
但是在进行试验时能够在嵌套的 for 循环中重用变量名真是太好了。 C++ 给了你这样的选择。