【问题标题】:Variables names ambiguity in C++C ++中的变量名称歧义
【发布时间】:2016-05-31 09:23:20
【问题描述】:

我对这种情况有点困惑:

#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++ 错了?因为做同样的事情但只是在函数的开头它给出了编译时错误。

【问题讨论】:

  • 这不是问题,但不要使用std::endl,除非您需要它的额外功能。 '\n' 结束一行。
  • @PeteBecker 哇,大师的建议是无法避免的 ;) 我从没想过 ::endl' 之间有一些区别'\n '。将通过一些关于它的参考资料。谢谢

标签: c++ ambiguous


【解决方案1】:

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

在块中声明的名称是该块的本地名称;它具有块范围。它的潜在作用域从其声明点开始,并在其块的末尾结束。在块范围内声明的变量是局部变量。

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

因为这样做但只是在函数的开头它给出了编译时错误。

您收到一个错误,因为 C++ 标准在第 3.3.3.2 节中明确禁止此类重新声明:

不得在函数定义的最外层块或与函数-try-block 关联的任何处理程序的最外层块中重新声明参数名称。

这种排除的原因是函数参数在函数的外部范围内是局部的,因此在没有另一层大括号的情况下重新声明会将重复的标识符引入同一范围。

【讨论】:

    【解决方案2】:

    我不介意这种 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++ 为您提供了这样的选择。

    【讨论】:

      【解决方案3】:

      是不是 C++ 错了?

      没有。重新声明一个标识符是完全合法的,只要它在不同的范围内。在这种情况下,范围是 if 语句的 then-body。

      这不是模棱两可的。将使用最近的前面声明。

      【讨论】:

      • 虽然有效,但一般不建议这样做,因为它可能会导致错误。
      【解决方案4】:

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

      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 所说,如果它们的范围不同,重新声明总是有效的。在这种情况下,属于内部作用域的变量将超过外部作用域。

      【讨论】:

        猜你喜欢
        • 2016-09-20
        • 1970-01-01
        • 1970-01-01
        • 2020-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-02
        • 2015-10-08
        相关资源
        最近更新 更多