6

このコードは、悪い習慣として扱われるべきだと私が考えるものを示しており、変数の再定義またはマスクに関するコンパイラからの警告を引き出します。

#include <iostream>

int *a;

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

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

その出力 (g++ でコンパイル):

0
0x602010

私はいくつかの参考文献 (Stroustrup と The Complete C++ Reference) を見てきましたが、これが許可される時期と理由については何も見つかりません。ただし、それが単一のローカルスコープ内にないことは知っています。

いつ、なぜこれが許可されるのですか? この構造の良い用途はありますか? どうすればg ++に警告してもらうことができますか? 他のコンパイラはそれについて不平を言っていますか?

4

6 に答える 6

15

これが許可されている理由については、これは完全に有効です。

f() 関数内にいるときは、ローカル スコープを定義しています。ローカル スコープはグローバル スコープをオーバーライドするため、「a」変数を定義すると、グローバル スコープが「非表示」になります。int *a;

于 2009-06-06T00:16:11.843 に答える
10

これは完全に有効ですが-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

于 2009-06-06T00:17:22.043 に答える
6

グローバル識別子のオーバーライドを安全に無視できるようにするために許可されています。基本的に、実際に使用するグローバル名だけを気にする必要があります。

あなたの例では、f()最初に定義されていたとします。次に、他の開発者がグローバル宣言を追加しました。以前は機能していた名前を追加することでf()、引き続き機能します。オーバーライドがエラーだった場合、関数は、新しく追加されたグローバル変数で何も実行しなくても、突然動作を停止します。

于 2009-06-06T00:19:01.167 に答える
4

多くの言語では、この種のことが許可されています。
通常、(すべての言語に関して) 最もローカルに定義された変数は、参照している変数でもあります。私が使用した 20 以上の言語のうち、これは非常に一般的です。

また、ほとんどの言語では、外側のスコープにあるものを明示的に参照できます。
たとえば、C++ では、:: 演算子を使用してグローバル スコープで変数を指定できます。

#include  <iostream>


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

    std::cout << a << "\n" << ::a << "\n";
            // Local
                           // global
}
于 2009-06-06T00:17:06.817 に答える
1

これが許可されている場合に答えるには: 基本的に、ネストされた 2 つのスコープで。

例えば:

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.

さて、答えは明らかに、同じスコープ内に単一の名前を持つ 2 つの「もの」を持つことが一般的に許可されているということです。これが可能なのは、そのスコープで実際に定義されている名前が多くても 1 つであるためです。他のものは、その範囲内で見えるだけです。複数の候補がある場合は、名前解決規則によってどの名前が選択されるかが決まります。

コンパイラが代替案を選択するたびに警告を出すのは本当に望ましくありません。これにより、オーバーロードやスマート テンプレート コードなどの無害なことについて、大量の警告が表示されます。

于 2009-06-08T09:14:15.400 に答える
0

他の人が述べたように、これは完全に合法であり、コンパイラにとって明確です。

ただし、これはプログラミング言語の多くの機能の 1 つであり、混乱や見つけにくいバグを引き起こす可能性があります。これらの変数のそれぞれに異なる名前を付けるのは簡単なので、わかりやすくするために、常にそうすることをお勧めします。

于 2009-06-06T14:55:21.003 に答える