首页 > 解决方案 > 访问由 C++ 中的局部声明隐藏的封闭范围(非全局)中的变量?

问题描述

范围解析运算符::可用于访问被局部声明遮蔽的全局变量。对于在封闭范围中声明但不是全局的变量,您如何实现相同的效果?

int main() {
  int i = 10;

  if (1) {
    int i = 5;
    std::cout << "Local i: " << i << std::endl;

    std::cout << "Main's i: " << ?? << std::endl; //How to access main's i?
  }

  return 0;
}

我知道这是不好的做法。但我只是想知道这是否可能。我认为不是。

解释为什么它不可能或它是如何有用的。

标签: c++

解决方案


不幸的是,这是不可能的。编译器警告选项,例如-WshadowGCC,可以帮助避免这种情况:

-W阴影

每当局部变量或类型声明遮蔽另一个变量、参数、类型、类成员(在 C++ 中)或实例变量(在 Objective-C 中)或内置函数被遮蔽时发出警告。请注意,在 C++ 中,如果局部变量隐藏了显式 typedef,编译器会发出警告,但如果它隐藏了 struct/class/enum,则不会发出警告。与 -Wshadow=global 相同。

例如,在您的示例中,您会收到如下警告:

:在函数“ int main()”中:

:7:9: 错误:“ i”的声明遮蔽了先前的本地 [-Werror=shadow]

7 |     int i = 5;

  |

正如@LF在下面的评论中指出的那样,您可以使用引用来访问另一个i

#include <iostream>

int main() {
  int i = 10;
  if (1) {
    int& nonlocal_i = i; // just before shadowing
    int i = 5;
    std::cout << "Local i: " << i << std::endl;
    std::cout << "Main's i: " << nonlocal_i  << std::endl;
  }
  return 0;
}

-Wshadow仍然会抱怨,如果您要加倍努力寻找替代名称,您可以以i不同的方式命名本地。


注意: 正如user4581301在评论中指出的那样,代码 likeint& i = i;不会在内部范围内完成您所期望的:

#include <iostream>

int main()
{
    int i = 4;
    {
        int& i = i;
        std::cout << i;
    }
}

它尝试使用变量i来初始化自己。在 Microsoft 的编译器中,您会收到如下编译错误:

错误 C4700:使用了未初始化的局部变量“i”

在 GCC 中,如果您打开所有警告,您会收到以下消息:

错误:引用 'i' 用自身初始化 [-Werror=init-self]

但是如果你没有打开警告,它会默默地编译并做错事


推荐阅读