C++ 在C++;,什么时候相同名称的两个变量可以在同一范围内可见?

C++ 在C++;,什么时候相同名称的两个变量可以在同一范围内可见?,c++,standards,warnings,compiler-warnings,C++,Standards,Warnings,Compiler Warnings,这段代码说明了一些我认为应该被视为不好的做法的东西,并从编译器中引出关于重新定义或屏蔽变量的警告: #include <iostream> int *a; int* f() { int *a = new int; return a; } int main() { std::cout << a << std::endl << f() << std::endl; return 0; } 我看过一些参考文献(Strou

这段代码说明了一些我认为应该被视为不好的做法的东西,并从编译器中引出关于重新定义或屏蔽变量的警告:

#include <iostream>

int *a;

int* f()
{
  int *a = new int;
  return a;
}

int main()
{
  std::cout << a << std::endl << f() << std::endl;
  return 0;
}

我看过一些参考文献(Stroustrup和完整C++参考),找不到什么时候和为什么允许这样做。但我知道它不在一个局部范围内


何时以及为什么允许这样做?这个构造有什么用处吗?我怎样才能让g++警告我呢?其他编译器对此会抱怨吗?

至于为什么允许这样做:这是完全正确的


当您在f()函数中时,您正在定义一个局部作用域。局部作用域覆盖全局作用域,因此在此处定义“a”变量“隐藏”全局
int*a

很多语言都允许这样做。
通常(对于所有语言而言),最局部定义的变量也是您所引用的变量。在我使用的20多种语言中,这是非常常见的

此外,大多数语言允许您显式引用外部范围中的语言。
例如,C++允许您用::运算符,< /p>在全局范围内指定变量。
#include  <iostream>


int a = 5;
int main()
{
    int a = 6;

    std::cout << a << "\n" << ::a << "\n";
            // Local
                           // global
}
#包括
INTA=5;
int main()
{
INTA=6;

std::cout这是完全正确的,但我认为使用
-Wall
只能在对参数进行阴影处理时收到警告

如果在对任何类型的变量进行阴影处理时需要警告,可以从
g++
手册页面使用:

   -Wshadow
       Warn whenever a local variable shadows another local variable, 
       parameter or global variable or whenever a built-in function is 
       shadowed.

请注意,默认情况下,
-Wshadow
不包括在
-Wall
中。

允许这样做,以便您可以安全地忽略全局标识符重写。本质上,您只需要关心实际使用的全局名称


假设在您的示例中,首先定义了
f()
,然后其他开发人员添加了全局声明。通过添加名称,
f()
以前可以工作,现在仍然可以工作。如果重写是一个错误,那么函数会突然停止工作,即使它对新添加的全局变量没有任何作用。

正如其他人所提到的,这是完全合法的,并且对编译器来说是明确的


然而,这是编程语言中可能导致混淆或难以发现错误的许多功能之一。由于为每个变量指定不同的名称很简单,为了清楚起见,我始终建议这样做。

在允许的情况下回答:基本上在任意两个嵌套范围内

例如:

void foo() {
    int a;
    {
        int a;
    }
}

class Base {
    int a;
};
class Derived: public Base {
    int a; // Yes, the name Base::a is visible in the scope of Derived, even if private
};

class Foo() {
    int a;
    Foo(int a) : a(a) { } // Works OK
};

using std::swap;
void swap(MyClass& lhs, MyClass& rhs);
// Not strictly a variable, but name lookup in C++ happens before determining 
// what the name means.
现在,答案必须是明确的,通常允许在同一范围内有两个名称相同的“事物”。这是可能的,因为最多一个名称实际上是在该范围内定义的;其他名称仅在该范围内可见。如果有多个候选名称,则名称解析规则决定选择哪个名称


你真的不想对编译器在不同选项之间进行选择的每一种情况都给出警告。这会给你很多警告,比如重载和一些智能模板代码。所有语言都允许这种情况。我的TI-85计算器上的编程语言不允许。所有变量都是全局变量,并且没有名称隐藏。NET(VB,C#)也不允许这样做!C#禁止阴影在我使用高阶函数时让我非常恼火。据我所知,基本语言(VB,内置TI程序)没有真正的范围定义,这就是为什么不允许阴影。
void foo() {
    int a;
    {
        int a;
    }
}

class Base {
    int a;
};
class Derived: public Base {
    int a; // Yes, the name Base::a is visible in the scope of Derived, even if private
};

class Foo() {
    int a;
    Foo(int a) : a(a) { } // Works OK
};

using std::swap;
void swap(MyClass& lhs, MyClass& rhs);
// Not strictly a variable, but name lookup in C++ happens before determining 
// what the name means.