web-dev-qa-db-ja.com

グローバルスコープとグローバルネームスペース

グローバルスコープとグローバルネームスペースという2つのフレーズの使用法を見ました。それらの違いは何ですか?

59
scdmb

C++では、すべての名前にはスコープがあり、その外側には存在しません。スコープはさまざまな方法で定義できます。namespacefunctionsclasses、および単に{}で定義できます。 =。

したがって、グローバルまたはそれ以外のネームスペースはスコープを定義します。グローバル名前空間は、::、およびこのネームスペースで定義されているシンボルは、グローバルスコープを持つと言われます。シンボルは、キーワードnamespaceで始まるブロック内で定義されているか、クラスのメンバーまたは関数のローカル変数でない限り、デフォルトでグローバル名前空間に存在します。

int a; //this a is defined in global namespace
       //which means, its scope is global. It exists everywhere.

namespace N
{
     int a;  //it is defined in a non-global namespace called `N`
             //outside N it doesn't exist.
}
void f()
{
   int a;  //its scope is the function itself.
           //outside the function, a doesn't exist.
   {
        int a; //the curly braces defines this a's scope!
   }
}
class A
{
   int a;  //its scope is the class itself.
           //outside A, it doesn't exist.
};

また、nameは、名前空間、関数、またはクラスのいずれかによって定義される内部スコープによって非表示にできることに注意してください。したがって、名前空間a内のNという名前は、グローバルなネームスペースでaという名前を隠します。同様に、関数とクラスの名前はグローバル名前空間の名前を隠します。このような状況に直面した場合は、::aは、グローバル名前空間で定義された名前を参照します。

int a = 10;

namespace N
{
    int a = 100;

    void f()
    {
         int a = 1000;
         std::cout << a << std::endl;      //prints 1000
         std::cout << N::a << std::endl;   //prints 100 
         std::cout << ::a << std::endl;    //prints 10
    }
}
82
Nawaz

「スコープ」は「名前空間」よりも一般的な用語です。すべての名前空間、クラス、およびコードブロックは、内部で宣言された名前を使用できるスコープを定義します。名前空間は、クラスおよび関数の外部で宣言された名前のコンテナです。

「グローバルスコープ」と「グローバルネームスペース」は、ほぼ同じ意味で使用できます。名前空間で宣言された名前のスコープは、その名前空間全体をカバーします。名前空間を具体的に参照する場合は「名前空間」を使用し、名前空間内の名前の可視性を参照する場合は「スコープ」を使用します。

4
Mike Seymour

スコープはオブジェクトの存続期間を示し、プログラムが実行される限り存在するグローバル変数を持つことができます。または、コードのブロックが実行される限り存在するブロックスコープを持つ変数を持つことができます。この例を考えてみましょう:

#include <iostream>

int a = 100;

main () {
    int a = 200;

    std::cout << "local a is: " << a << std::endl;
    std::cout << "global a is: " << ::a << std::endl;

    return 0;
}

実行すると、ステートメントはlocal a is: 200、これは明らかに期待されます。なぜなら、amainを再定義しているからです。また、グローバル::aこれは、期待される値100を再び出力します。これは、グローバル名前空間を要求したためです::

名前空間のセマンティクスはほとんど論理的です。名前の衝突を回避するためにsymbloを相互に分離する方法であり、オブジェクトの寿命には影響しません。

一方、スコープは、オブジェクトの寿命を示します。グローバルaは、mainが実行されるよりもはるかに早く構築されるため、ローカルaの前に存在します。ただし、スコープはforcesシンボルのネームスペースでもありますが、namespaceとは異なります。 globalclassfunctionblockfileなど、さまざまな種類のスコープがあります。

紛らわしい部分は、特定のシンボルの可視性を示すためにスコープがオーバーロードされる場合があることです。これは、ネームスペースの概念が存在せず、寿命と可視性の両方を示すためにスコープが使用されたCただし、C++ではルールが少し変更されましたが、2つの言語は多くの概念を共有しているため、scopeという用語が引き続き同じように使用されます。

4
dryajov

たとえば、グローバル変数int iを宣言する場合、i is in the global namespaceおよびhas the global namespace scopeと言います。それで全部です。

C++ 03からの抜粋:

3.3.5 Namespace scope   

    The outermost declarative region of a translation unit is also a namespace, called
  the global namespace. A name declared in the global namespace has global namespace
  scope (also called global scope).
3
Eric Z

@Dmitriy Ryajov

トピックは少し古いですが、これについてのヘルプを提供したいと思います。物事を実際よりも複雑にすべきではないと思います。識別子のScopeは、プログラム内のエンティティを参照する名前である識別子を使用して、参照されたエンティティを見つけることができるコンピュータプログラムの一部です。したがって、スコープという用語は識別子にのみ適用され、オブジェクトの有効期間と混合しないでください。それらは多少つながっていますが、混同しないでください。オブジェクトの寿命は、そのオブジェクトにメモリを割り当てる場所によって示されます。したがって、たとえば、メモリがスタックに割り当てられている場合、関数が終了するとすぐに解放されます。そのため、オブジェクトを保存する場所に依存し、それはそのライフタイムを示します。スコープには、「これはオブジェクトの名前であり、それまではこの名前をオブジェクトに使用できます」としか書かれていません。したがって、私が言ったように、用語scopeはオブジェクトの識別子のみであり、ライフタイムはオブジェクトを格納する場所によって示される別のものです。

さらに、linkageについてこれと密接に関連することを言いたいと思います。これは時々混乱することもあります。 translation unitにいくつかのオブジェクトを参照する識別子があるとします。 other翻訳単位の同じ識別子が同じエンティティを参照するかどうかは、リンケージによって示されます。したがって、たとえば、識別子に外部リンケージがある場合、キーワードexternで宣言することにより、この識別子が参照するエンティティを参照できますが、他の翻訳単位からは参照できます。ここで、そのエンティティを他の翻訳単位で使用したくないとしましょう。その後、エンティティはプログラムが終了するまでexistしますが、宣言しないと参照できなくなります。また、リンケージとライフタイムという用語を混在させていることに注意してください。ただし、これはglobalエンティティのみに外部リンケージがあるためです。関数内の識別子は、プログラムの他の部分からは参照できません。

結論:常に物事をシンプルにするようにしてください。私は、異なる人々がこれらの用語について異なる方法で話すことに驚いた。ほぼ同じ意味を持つ複数の用語があり、おそらく誰もがこの時点で動けなくなるため、個別のコンパイルのプロセス全体は混乱します。

2
LearningMath