web-dev-qa-db-ja.com

変数のスコープとはどういう意味ですか?

変数のスコープは-

「特定の変数のスコープは、その変数がコンパイラによって認識されるプログラムのソースコード内の範囲です。」.

そのステートメントは、数か月前に読んだ "C++での変数のスコープと寿命" からのものです。

最近私はLeMoyne-Owen Collegeコースでこれに遭遇しました:

http://sankofa.loc.edu/CHU/WEB/Courses/Cosi350/Ch4/scope.13.gif

C#と(C99、C++、Java)の変数のスコープの違いは何ですか?

ただし、変数は使用する前に宣言する必要があります

7
jsp99

変数の「スコープ」とはどういう意味ですか?変数のスコープは、「特定の変数のスコープは、その変数がコンパイラによって認識されるプログラムのソースコード内の範囲です」と考えてください。

その定義は、C#仕様のスコープの定義と一致します。それは言う:

名前のスコープは、プログラムテキストの領域であり、その中で、名前の修飾なしに名前で宣言されたエンティティを参照することができます。

C#仕様では、スコープを持つnameであることに注意してください。一部の変数には名前がないため、スコープがありません。そして、いくつかのものには名前がありますが、変数ではありません。クラス名、名前空間名、関数名などはすべてスコープを持っています。

ローカル変数のスコープは、しばしばlifetimeと混同されます。ローカル変数の存続期間は、そのスコープに関連する場合があります。コントロールがローカルのスコープを離れると(通常の方法または例外を介して)、ローカルは誰にも気付かれずに破棄されます。ただし、ランタイムは許可ローカル変数の存続期間を作成しますshorter誰にも気付かれずに実行できる場合。ランタイムは許可でもあり、ローカル変数をそのスコープよりも長く存続させます。そして、ローカル変数が必須である状況がいくつかあり、コントロールがそのスコープを離れたときにそれを超えて生きます。 (たとえば、ローカルがラムダの閉じた外側の変数である場合。)

したがって、「スコープ」を「ライフタイム」の同義語として使用することは賢明ではありません。それらはしばしば関連していますが、かなり異なる場合があります。 「スコープ」は、「変数が有効な期間」ではなく、「名前が有効なテキストの領域」を意味するために使用します。 スコープは基本的にコンパイル時の概念です

C#と(C99、C++、Java)の変数のスコープの違いは何ですか

C、C++、またはJavaの違いの短いリストを提供するための正確なスコープ規則)について十分に詳しくありません。ただし、C#のいくつかの奇妙な点を指摘できます。

1つ目は、C#では、ローカル変数がスコープthroughoutのブロックにあることです。

class C
{
    int x;
    void M()
    {
        int y = x;
        int x = y;
    }
}

C++では、最初の「x」は「this.x」を意味します。これは、ローカル変数xが宣言されるまでスコープ内にないためです。 C#では、ローカル変数xはブロック全体でスコープ内にあります。宣言の前にスコープ内にあるローカルを使用すると、C#ではエラーになります。

2つ目は、C#では、単純な名前は最初に使用されるスコープ全体で同じ名前を意味する必要があることです。

class C
{
    int x;
    void M()
    { // M starts
        int y = x;
        if (y > 100)
        {
            int x = y;
        }
    }
}

「M開始」というラベルの付いたブロック内では、単純な名前「x」が2つの異なることを意味するために使用されるため、これは不正です。ローカルがスコープ内にないため、最初の「x」は「this.x」を意味します。ただし、同じ名前を2つの異なる意味で使用することは違法です。これはバグの原因であるためです。

この主題に興味があるなら、私はそれにいくつかの記事を書いています。見る

http://blogs.msdn.com/b/ericlippert/archive/tags/scope/

http://blogs.msdn.com/b/ericlippert/archive/tags/declaration+spaces/

更新:単純な名前はそれを囲むブロック全体で一意の意味を持つ必要があるというルールがC#6で緩和されました。言語の設計チームは、ユーザーの混乱のコストが高すぎてバグをキャッチできないため、高すぎると判断しました。

12
Eric Lippert

ここでの「スコープ」という用語は、変数が人生に存在する時間を指します。コンストラクタが呼び出されたときに開始し、デストラクタが呼び出されたときに終了します。

C++とJava=では、変数はその定義に遭遇すると存在し始め、そのような定義を含むブロックの終わりに到達すると存在を終了します(シーケンシャルフローまたは "ジャンプ-break」、「goto」、「return」、「throw」のような「先読み」命令)

C#では、ブロックで宣言されたすべての変数はブロックの入り口で作成されますが、それらの定義に従って初期化されます(そのため、それらは割り当てられた領域に関してすでに「存在」しているため、以前は使用できません。既知)

ローカルブロック内では、これはより洗練されており、プログラマにrealの違いはありませんが、-より広いスコープで-コンパイラが「循環」の存在下でもコードを生成できるようにします依存関係」、C++では、ヘッダーガードや2フェーズ構成などの他のトリックで回避する必要があります。

4

C++およびJava=の場合、次のコードは有効ですが、C#ではこの競合が発生します。「ローカル変数 'logging'は、このスコープで宣言できません'、これはすでに子スコープで使用されています。」.

// Statically check script.
{
    Boolean logging = false;
    MyClass.check(script, logging);
}

// Translate code.
Boolean logging = true;
MyClass.translate(script, logging);
0
intrepidis