C++ 言語では、変数をグローバルに宣言するデメリットはありますか?
void foo()
{
int a;
a=10;
}
int a;
void foo()
{
a=10;
}
それらの間に違いはありますか?
C++ 言語では、変数をグローバルに宣言するデメリットはありますか?
void foo()
{
int a;
a=10;
}
int a;
void foo()
{
a=10;
}
それらの間に違いはありますか?
- 非局所性-- ソース コードは、個々の要素の範囲が限定されている場合に最も理解しやすくなります。グローバル変数は、プログラムのどの部分でも読み取ったり変更したりできるため、考えられるすべての用途を覚えたり推論したりすることが難しくなります。
- アクセス制御や制約チェックなし-- グローバル変数はプログラムのどの部分からでも取得または設定でき、その使用に関するルールは簡単に破られたり忘れられたりする可能性があります。(つまり、get/set アクセサーは、直接データ アクセスよりも一般的に好まれます。これは、グローバル データの場合はなおさらです。) さらに言えば、アクセス制御の欠如は、信頼できないコードを実行したい状況でのセキュリティの実現を大きく妨げます。 (サードパーティのプラグインの操作など)。
- 暗黙の結合-- 多くのグローバル変数を含むプログラムでは、多くの場合、これらの変数の一部が密接に結合され、変数と関数が結合されます。結合された項目をまとまりのある単位にグループ化すると、通常、より良いプログラムにつながります。
- 並行性の問題-- グローバルが複数の実行スレッドからアクセスできる場合、同期が必要です (そして、あまりにも頻繁に無視されます)。モジュールをグローバルに動的にリンクする場合、数十の異なるコンテキストでテストされた 2 つの独立したモジュールが安全であっても、構成されたシステムはスレッドセーフではない可能性があります。
- 名前空間の汚染-- グローバルな名前はどこでも利用できます。ローカルを使用していると思っているときに (つづりを間違えたり、ローカルの宣言を忘れたりして)、無意識のうちにグローバルを使用してしまう場合や、その逆の場合もあります。また、同じグローバル変数名を持つモジュールをリンクする必要がある場合、運が良ければリンク エラーが発生します。運が悪いと、リンカは同じ名前のすべての使用を同じオブジェクトとして単純に扱います。
- メモリ割り当ての問題-- 一部の環境には、グローバルの割り当てを難しくするメモリ割り当てスキームがあります。これは、「コンストラクター」が割り当て以外の副作用を持つ言語で特に当てはまります (その場合、2 つのグローバルが相互に依存する危険な状況を表現できるため)。また、モジュールを動的にリンクする場合、異なるライブラリに独自のグローバル インスタンスがあるかどうか、またはグローバルが共有されているかどうかが不明な場合があります。
- テストと閉じ込め- グローバルを利用するソースは、実行の間に「クリーンな」環境を簡単に設定できないため、テストがやや難しくなります。より一般的には、ソースに明示的に提供されていない何らかのグローバル サービス (ファイルやデータベースの読み取りと書き込みなど) を利用するソースは、同じ理由でテストが困難です。通信システムの場合、システムの不変条件をテストするには、システムの複数の「コピー」を同時に実行する必要がある場合があります。これは、テストの一部として共有するために提供されていない共有サービス (グローバル メモリを含む) の使用によって大きく妨げられます。 .
グローバル変数のメモリは自動的に解放されません。スコープ変数のメモリは、ブロックが完了するとすぐに解放されます。
void foo()
{
int a;
a=10;
}
これint a
は終了後に解放されますfoo
int a;
void foo()
{
a=10;
}
これint a
は、外部のスコープに応じて解放されますfoo()
最初の例では、変数はスタック上に存在し、関数が終了するまでのみ有効であり、関数内からのみ表示されます。2 つ目は、有効であり、外部からアクセスできることです。
原則として、変数は常に可能な限りローカルとして宣言する必要があるため、本当に必要な場合にのみグローバル変数を使用してください。
3 番目のバリアントがあります。これを行う場合:
void foo()
{
static int a;
a=10;
}
その後、関数が終了した後も変数は有効なままですが、内部からのみ表示されます (ただし、必要に応じてポインターまたは参照を提供できます)。これは、関数呼び出し間で値を保持する必要があるが、関数内からのみ使用される変数が必要な場合に推奨される使用法です。
これは、StackOverflow で以前に説明されています。たとえば、これを参照してください。
https://stackoverflow.com/a/485020/980195
変数をグローバル スコープに置くことの主な欠点は、それらがグローバルにアクセス可能になることです。他のコードは、それらの読み取りまたは書き込みを決定できます。一方、ローカル変数では、値を変更したり値にアクセスしたりできるすべてのものを知るために、ローカルスコープを見るだけで済みます。
それとは別に、それをグローバル名前空間に置くことは、名前の衝突、あいまいさ、または単純なタイプミスによって間違った変数を誤って参照するユーザーさえも引き起こす可能性があることを意味します. これは、変数を自分の場合のように単純なものと呼ぶ場合に特に悪いことです。
他にも理由があります。たとえば、@naren が提供した回答を見てください。
メモリ使用量。最初のケースではメモリが解放されますが、2 番目のケースでは解放されません。そして、''A'' のような名前の変数をグローバル変数として宣言するのは非常に悪いことです。これは、多数のエラーの原因となります。