グローバルスコープとグローバル名前空間の2つのフレーズの使用法を見ました。それらの違いは何ですか?
5 に答える
C++ では、すべての名前に、それが存在しない範囲外のスコープがあります。スコープはさまざまな方法で定義できます。名前空間、関数、 クラス、および単に{}で定義できます。
したがって、名前空間は、グローバルであろうとなかろうと、スコープを定義します。グローバル名前空間は using を参照し::
、この名前空間で定義されたシンボルはグローバル スコープを持つと言われます。シンボルは、デフォルトではグローバル名前空間に存在しますが、それが keyword で始まるブロック内で定義されている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.
};
また、名前空間、関数、またはクラスのいずれかで定義された内部スコープによって名前が隠される可能性があることにも注意してください。したがって、名前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
}
}
int i
たとえば、グローバル変数を宣言するときはi is in the global namespace
、 and と言い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).
「スコープ」は「名前空間」よりも一般的な用語です。すべての名前空間、クラス、およびコード ブロックは、その内部で宣言された名前を使用できるスコープを定義します。名前空間は、クラスおよび関数の外部で宣言された名前のコンテナーです。
「グローバル スコープ」と「グローバル名前空間」は、ほぼ同じ意味で使用できます。名前空間で宣言された名前のスコープは、その名前空間全体をカバーします。特に名前空間を参照している場合は「名前空間」を使用し、その中の名前の可視性を参照している場合は「スコープ」を使用します。
スコープはオブジェクトの存続期間を示します。プログラムが実行される限り存在するグローバル変数を持つことができます。また、コードのブロックが実行される限り存在するブロックスコープを持つ変数を持つこともできます。次の例を検討してください。
#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
、 が出力されますが、これは当然のことです。なぜなら、それを囲むブロックのスコープ内でどのリーフを再定義a
しているのかからです。また、グローバル namespace を要求したため、期待値 100 を再度出力するmain
global も出力します。::a
::
名前空間のセマンティクスはほとんど論理的であり、名前の衝突を避けるためにシンボルを互いに分離する方法であり、オブジェクトの寿命には影響しません。
一方、スコープはオブジェクトの寿命を示します。メインが実行されるよりもはるかに早く構築されるため、グローバルa
はローカルの前に存在します。a
ただし、スコープもシンボルに名前空間を強制namespace
しますが、a とは異なります。、、、、などglobal
、さまざまな種類のスコープがあります...class
function
block
file
紛らわしい部分は、特定のシンボルの可視性を示すためにスコープがオーバーロードされることがあるということです。これは、名前空間の概念が存在せず、有効期間と可視性の両方を示すためにスコープが使用されていた C から借用したものです。ただし、C++ ではルールが少し変更されましたが、2 つの言語は多くの概念を共有しているため、スコープという用語は同じように使用されています。
@ドミトリー・リャヨフ
トピックは少し古いですが、これについて助けを提供したいと思います。物事を実際よりも複雑にするべきではないと思います。Scope
識別子の一部は、プログラム内のエンティティを参照する名前である識別子を使用して、参照されたエンティティを見つけることができるコンピュータープログラムの一部です。したがって、スコープという用語は識別子にのみ適用され、オブジェクトの有効期間と混同してはなりません。それらはある程度関連していますが、混同してはいけません。オブジェクトの寿命は、そのオブジェクトにメモリを割り当てる場所によって示されます。したがって、たとえば、メモリがスタックに割り当てられている場合、関数が終了するとすぐに解放されます。したがって、オブジェクトを保存する場所に依存し、それはその寿命を示します。スコープには、「これはオブジェクトの名前であり、それまではこの名前をオブジェクトに使用できます」とのみ表示されます。だから、私が言ったように、用語scope
オブジェクトの識別子のみであり、ライフタイムはオブジェクトを保存する場所によって示される別のものです。
linkage
さらに、これと密接に関係することについて言いたいことがあります。これも時々混乱することがあります。translation unit
いくつかのオブジェクトを参照する にいくつかの識別子があるとしましょう。翻訳単位の同じ識別子がother
同じエンティティを参照するかどうかは、リンケージによって示されます。したがって、たとえば、識別子に外部リンケージがある場合、この識別子が参照するエンティティを参照できますが、キーワードで宣言することにより、他の翻訳単位から参照できますextern
。ここで、そのエンティティを他の翻訳単位で使用したくないとしましょう。その後、エンティティはexist
プログラムが終了するまで存在しますが、宣言しないと参照できなくなります。また、リンケージとライフタイムという用語を混在させていることにも注意してください。しかし、これは単にglobal
エンティティには外部リンケージがあります。関数内の識別子は、プログラムの他の部分から参照できません。
結論: 常に物事をシンプルに保つようにしてください。これらの用語について、人によって話し方が異なることに驚きました。ほぼ同じ意味を持つ複数の用語があり、おそらく誰もがこの時点で行き詰まってしまうため、個別のコンパイルのプロセス全体は混乱を招きます。