グローバル変数は悪いですか?[閉まっている]


247

C / C ++では、グローバル変数は教授が考えるほど悪いのですか?


17
彼が冗談を言っている場合に備えて私は噛みます...「彼らはどれほどひどいですか」?
Zach Scrivena、2009年

13
この質問はかなり面白かったと思います!ソフトウェア開発は、最初から同じ古い落とし穴に直面しており、プログラマーはグローバル変数、goto、短い名前付き変数を使用することが問題ではないことをまだ知らないことがよくあります。悪いコードはそれらを使わずに毎日書かれています。+1
シルヴァン

69
どうすれば答えられるでしょうか?彼は彼の教授が彼らがどれほど悪いと思っているかについて私たちに話していません。:)
スティーブファローズ

9
@ファンメンデス私は100%あなたに同意します!私が話していた問題は、多くの開発者がグローバル変数を使用してはならないことを知っているが、理由がわからないことです!そして、私は、すべての関数が+100フィールドを含む同じ巨大構造を受け取る多くの大きなソフトウェアを見てきました-お母さん、グローバル変数なし!いわゆる「グッドプラクティス」と同じ問題:それらはすべてのコンテキストではなく、いくつかのコンテキストでのグッドプラクティスです。それらを使用すると、保守不可能なコードが作成される場合があります。乾杯。
Sylvain Rodrigue

3
グローバル変数の良い使い方はほとんどありません。可能ではあるが議論の余地のある使用法は、起動時に一度設定ファイルを読み込むグローバルな「設定」オブジェクトでしょう。
Siler、2014

回答:


256

グローバル変数の問題は、すべての関数がこれらにアクセスできるため、これらの変数を実際に読み書きする関数を理解することがますます難しくなることです。

アプリケーションがどのように機能するかを理解するには、グローバル状態を変更するすべての関数を考慮する必要があります。それは可能ですが、アプリケーションが大きくなると、事実上不可能(または少なくとも完全に時間の無駄)になるほど難しくなります。

グローバル変数に依存しない場合、必要に応じて異なる関数間で状態を渡すことができます。このようにすると、グローバルな状態を考慮する必要がないため、各関数の機能を理解できる可能性が高くなります。


9
この答えは本当に良いです。「変数のスコープを最小限に抑える」解答と組み合わせるstackoverflow.com/questions/357187/...
bobobobo

17
「アプリケーション」を「クラス」に、「グローバル状態」を「オブジェクト状態」に置き換え、クラスでメンバー変数(別名フィールド)を使用しない場合とまったく同じ引数を作成します。本当の答えは、適切なときにそれらを使用することです。
Ian Goldby

2
いくつかの(おそらくばかげた)質問:1)これらの変数を読み書きする関数を知りたい場合、エディターで「検索」関数を使用して、これらの変数の値が変更されるケースを見つけることはできませんか?2)「それは可能です...時間の完全な浪費です。」例を挙げていただけますか?3)「グローバル変数に依存しない場合、...グローバル状態を考慮する必要はありません。」それがどのように有利であるか私にはわかりません。おそらく、その一例が私にとってはうまくいくでしょう。
Andrei

2
@boboboboリンク切れ、1万人以上のユーザーからスクリーンショットを取得できますか?
noɥʇʎԀʎzɐɹƆ

3
@noɥʇʎԀʎzɐɹƆどうぞ!i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq

85

重要なことは、全体的な目標を明確にすることです。

ほとんどの場合、グローバル変数によりコードの意味が不明確になるため、「グローバル変数なし」というルールがあります。

ただし、多くのルールと同様に、人々はそのルールを覚えており、そのルールが意図していたことを覚えていません。

グローバル変数の悪を回避するためだけに膨大な数のパラメーターを渡すことにより、コードのサイズを2倍にするプログラムを見たことがあります。結局のところ、グローバルを使用すると、プログラムを読んでいる人にとってプログラムがより明確になります。ルールの言葉を不注意に固執することにより、元のプログラマーはルールの意図に失敗しました。

だから、はい、グローバルはしばしば悪いです。しかし、結局のところ、グローバル変数を使用することでプログラマーの意図がより明確になったと感じたら、先に進んでください。ただし、最初の部分がどのように機能するかを理解するために誰かに2番目のコード(グローバル)に強制的にアクセスさせると自動的に発生する明快さの低下を覚えておいてください。


8
変数を渡す代わりにグローバルを使用することを提案することは、コードを再利用できなくし、マルチスレッドに対して安全でなくなるためのレシピです
Juan Mendes

16
適切な状況でグローバルを提案することは、より明確で高性能なコードのレシピです。「受け渡し」には、一定のスタック動的メモリ割り当てが必要です。これは、着信ソケットデータのグローバルバッファなど、グローバルであるはずのものに対してはばかげています。たとえば、Winsockのrecv()を読み取る関数がある場合、すべての呼び出し内でこのバッファーを常に作成および割り当て解除するのはなぜですか?バッファをグローバルにします。とにかく、複数のスレッドがそれを読み取ることはありません。
ジェームズ

気になるのは、グローバル変数を回避するためにパラメーターを渡すことによって、どのプログラムがコードのサイズを2倍にするかです。私の経験では、グローバル変数を使用することでデータ公開の問題を解決できる可能性がありますが、通常、これらの魔法の変数が適切に動作するようにするには、追加の複雑なロジックを追加する必要があります。
user2167582

3
誰かが約100個の変数を渡している場合、オブジェクトが何であるかを学習していません。このオブジェクトへの参照を使用すると、最悪の場合、ポインタの周りを通過します。ルールは単なる明快さではなく、テスト容易性でもあると思います。非グローバルを使用すると、テストがはるかに簡単になる傾向があります。
UKMonkey

2
「誰かが約100個の変数を渡した場合、オブジェクトが何であるかを学習していません。」同意しましたが、すべての世界がオブジェクト指向であるわけではありません。コードサイズを2倍にする私の個人的な例は、1986年頃の大規模なFortranプログラムでした。大学の新入社員として、各呼び出しに約30のパラメーターを追加し、すべてのグローバルを排除することで、それを「改善」しました。その後、私が鍛えたものに気づいたときの私の改善を元に戻しました。
トムウェスト

64

私の教授は以前に次のようなことを言っていました:グローバル変数の使用は、正しく使用すれば大丈夫です。私は今までそれらを正しく使うのが得意ではなかったと思うので、ほとんど使用しませんでした。


25
仰るとおり。それらはgotoのようなものです。
デビッドホルム

5
私の現在の会社では、staticグローバル変数を多用しています。言語はCです。比較的小さな翻訳単位に制限されているため、C ++オブジェクトのクラス変数に似ています。
Vorac、2014年

1
@Vorac静的変数はグローバル変数ではなく、ローカル変数です。グローバル変数は、プログラム内のどこでも使用できる変数です(つまり、「グローバル」です)。関数の外部で宣言された変数であるファイルスコープ変数と混同しないでください。静的ファイルスコープ変数はグローバル変数ではありません。
ランディン、2015年

1
、自分自身を修正するにはprogram lifetime, file scope variables。そして、あなたは(自動変数では不可能である)、外の世界への変数へのポインタを渡したら、彼らは非常にグローバルになる...
Vorac

@Lundin同意する、staticグローバル変数のスコープは同じ翻訳単位に限定されています。ただし、グローバル変数として、プログラムの終了までの寿命があります。
akhilesh1988 16

38

グローバル変数は、代替手段がない場合にのみ使用してください。そして、はい、それはシングルトンを含みます。90%の確率で、パラメーターを渡すコストを節約するためにグローバル変数が導入されます。そして、マルチスレッド/ユニットテスト/メンテナンスコーディングが発生し、問題が発生します。

したがって、はい、状況の90%でグローバル変数が不良です。例外はあなたの大学時代にあなたに見られることはほとんどありません。私が頭の中で考えている1つの例外は、割り込みテーブルなどの本質的にグローバルなオブジェクトを扱うことです。DB接続のようなものはグローバルに見えますが、そうではありません。


2
大学時代見た唯一の例外は、グラフィックスのコールバック関数でした。XWindowsでは、マウスコールバックにプログラム状態の任意のチャンクを渡すことができるvoid *データ引数がありませんでした...(とにかく、グローバルよりもはるかに優れているわけではありません...)
Brian Postow

10
「DB接続のようなものはグローバルに見えますが、そうではありません。」の+1
R .. GitHub ICEのヘルプの停止

1
割り込みテーブルはグローバルではなく、プロセッサごとに1つありますが、プログラムのインスタンスがプロセッサごとに1つあるため、「キャンセル」されます。
user253751

1
なぜDB接続がグローバルではないのか(そして何が良い代替手段になるのか)について誰かに教えてもらえますか?私はつねに、接続がグローバルが受け入れられるまれなケースの1つだと考えていました。
Floella

33

プログラマーのためにグローバル変数が作成する問題は、グローバル変数を使用しているさまざまなコンポーネント間のコンポーネント間結合面を拡張することです。これが意味することは、グローバル変数を使用するコンポーネントの数が増えると、相互作用の複雑さも増す可能性があるということです。この増加した結合により、通常、変更を加えるときに欠陥がシステムに注入されやすくなり、欠陥の診断と修正が難しくなります。この結合の増加により、変更を行うときに使用可能なオプションの数が減り、変更の結果を判別するためにグローバル変数も使用しているさまざまなモジュールをたどる必要があるため、変更に必要な労力を増やすことができます。

カプセル化の目的は、基本的にグローバル変数の使用とは逆ですが、結合を減らして、ソースの理解と変更をより簡単に、より安全に、より簡単にテストできるようにすることです。グローバル変数を使用しない場合は、単体テストを使用する方がはるかに簡単です。

たとえば、さまざまなコンポーネントがステートマシンとして使用する列挙型インジケーターとして使用されている単純なグローバル整数変数があり、新しいコンポーネントに新しい状態を追加して変更を加えた場合、他のすべてをトレースする必要があります。変更がコンポーネントに影響を及ぼさないようにするためのコンポーネント。考えられる問題の例としては、現在の各値のステートメントを含むswitch列挙型グローバル変数の値をテストするステートメントcaseがさまざまな場所で使用されており、一部のswitchステートメントでdefault処理するケースがない場合があります。アプリケーションに関する限り、突然予期しないグローバルな動作が発生します。

一方、共有データ領域を使用すると、アプリケーション全体で参照される一連のグローバルパラメータを含めることができます。このアプローチは、メモリフットプリントが小さい組み込みアプリケーションでよく使用されます。

これらの種類のアプリケーションでグローバル変数を使用する場合、通常、データ領域への書き込みの責任は単一のコンポーネントに割り当てられ、他のすべてのコンポーネントはその領域をその領域としてconst認識し、そこから読み取り、書き込みは行いません。このアプローチを取ると、発生する可能性のある問題が制限されます。

回避する必要があるグローバル変数からのいくつかの問題

構造体などのグローバル変数のソースが変更された場合、その変数を使用するすべてがその実際のサイズとメモリテンプレートを認識できるように、それを使用するすべてを再コンパイルする必要があります。

複数のコンポーネントがグローバル変数を変更できる場合は、グローバル変数にあるデータに一貫性がないという問題が発生する可能性があります。マルチスレッドアプリケーションでは、おそらく何らかのロック領域またはクリティカル領域を追加して、一度に1つのスレッドのみがグローバル変数を変更できるようにし、スレッドが変数を変更しているときにすべての変更が完了するようにする必要があります。他のスレッドが変数を照会または変更する前にコミットされます。

グローバル変数を使用するマルチスレッドアプリケーションのデバッグは、より困難になる可能性があります。あなたはに実行することができます競合状態で複製することが困難な欠陥を作成することができます。複数のコンポーネントがグローバル変数を介して通信するため、特にマルチスレッドアプリケーションでは、どのコンポーネントが変数を変更しているのか、いつどのように変数を変更しているのかを理解するのは非常に困難です。

名前の衝突は、グローバル変数の使用に関する問題になる可能性があります。グローバル変数と同じ名前のローカル変数は、グローバル変数を非表示にすることができます。また、Cプログラミング言語を使用すると、命名規則の問題が発生します。回避策は、特定のサブシステムのグローバル変数をすべて同じ最初の3文字で始めるサブシステムにシステムを分割することです目的Cでの名前空間の競合の解決については、こちらを参照してください)。C ++は名前空間を提供しますが、Cを使用すると、さまざまなデータ項目と、ファイルとして静的に提供されるデータおよび関数へのポインターをメンバーとするグローバルに表示される構造体を作成することでこれを回避できます。グローバルに見える構造体。

場合によっては、元のアプリケーションの意図が変更され、単一のスレッドの状態を提供するグローバル変数が変更されて、複数の重複するスレッドを実行できるようになります。例としては、状態のグローバル変数を使用する単一ユーザー向けに設計されたシンプルなアプリケーションがあり、リモートアプリケーションが仮想ユーザーとして機能できるようにRESTインターフェースを追加する要求が管理から降りてきます。したがって、グローバル変数とその状態情報を複製して、単一のユーザーとリモートアプリケーションの各仮想ユーザーが独自の一意のグローバル変数のセットを持つようにする必要があります。

C ++ namespaceとC のstructテクニックの使用

C ++プログラミング言語の場合、namespaceディレクティブは名前の衝突の可能性を減らすのに非常に役立ちます。namespaceとともにclass、さまざまなアクセスキーワード(、、)privateprotectedpublic変数をカプセル化するために必要なほとんどのツールを提供します。ただし、Cプログラミング言語はこのディレクティブを提供しません。このスタックオーバーフローの投稿であるNamespaces in CはCにいくつかのテクニックを提供します。

有用な手法は、structグローバルな可視性を持つとして定義されている単一のメモリ常駐データ領域を持ちstruct、その中に、公開されているさまざまなグローバル変数と関数へのポインターがあります。グローバル変数の実際の定義には、staticキーワードを使用してファイルスコープが与えられます。次に、constキーワードを使用して、読み取り専用を示す場合、コンパイラーは読み取り専用アクセスを強制するのに役立ちます。

このstruct手法を使用すると、グローバルをカプセル化して、たまたまグローバルになる一種のパッケージまたはコンポーネントにすることもできます。この種のコンポーネントを使用することで、グローバルとグローバルを使用する機能に影響を与える変更の管理が容易になります。

ただし、namespaceこのstruct手法は名前の衝突を管理するのに役立ちますが、グローバルの使用が特に最近のマルチスレッドアプリケーションで導入するコンポーネント間結合の根本的な問題は依然として存在しています。


これは最高の説明であり、そこにあるすべてを説明しています。賞賛!
johndoevodka

クラスカップリングを使いすぎないようにするためのコードルールが言語に必要です。
メルボルン開発者、

20

グローバル変数は、あなたが作ったのと同じくらい悪いものです。

完全にカプセル化されたプログラムを作成する場合は、グローバルを使用できます。グローバルを使用することは「罪」ですが、プログラミングの罪はかなり哲学的です。

L.in.oleumをチェックアウトすると、変数がグローバルのみである言語が表示されます。ライブラリはすべてグローバルを使用せざるを得ないため、スケーラブルではありません。

とはいえ、選択肢があり、プログラマーの哲学を無視できる場合、グローバルはそれほど悪くありません。

あなたがそれらを正しく使うならば、どちらも後藤ではありません。

大きな「悪い」問題は、それらを間違って使用すると、人々が悲鳴を上げ、火星着陸船が墜落し、世界が爆破されるということです...またはそのようなもの。


16
混乱した学生にグローバルを使用することの問題を軽視することは、良い考えではありませんIMO。
GEOCHET 2009年

3
設計哲学は客観的ではありません。少なからず。ほとんどのプログラマーが何かを好まないからといって、決してそのものを調べてはならないという意味ではありません。世界を終わらせることなく、グローバルを一般的に使用するのは簡単です。彼にそれをさせ、闘わせ(彼がそうすることを知っている)、そしてその方法を学びましょう。
user54650 2009年

7
リッチは正しいです。この答えは、彼らはすべてのことのように悪いようじゃないだけ」という、/悪いわけではない(またはどのようにグローバルが安全に使用することができます)されているものについては何も言いません。このように、それが唯一の問題を軽視。。
jalf

4
グローバル変数が「あなたがそれらを作るのと同じくらい悪い」だけであることに私は同意しません。特にマルチ開発者が相互に接続している世界のほとんどの人が生活し、仕事をし、プログラムしている主な問題の1つは、グローバル変数がELSEにコードを悪用する機会を与えることです。
gariepy

@gariepyまで私は話が静的に関するものですが:Dわかったので、それはそれです...そして私のアプリは1つまたは2つのグローバル変数しか持っていません、それはVisual Studio、DEBUGおよびTRACEに付属していますが、通常は使用しません:D
deadManN

19

はい。ただし、グローバル変数を使用するコードでの作業を中止し、グローバル変数を使用するコードを使用する何かを書き始めるまで、グローバル変数のコストは発生しません。しかし、コストはまだあります。

言い換えれば、それは長期的な間接費であり、そのためほとんどの人はそれは悪くないと考えています。


19

最高裁判所の裁判中にコードが徹底的に審査される可能性がある場合は、グローバル変数を回避するようにしてください。

この記事を参照してください: バギー呼吸器コードはソースレビューの重要性を反映しています

両方の調査で特定されたコードのスタイルにいくつかの問題がありました。レビューアが懸念した文体上の問題の1つは、保護されていないグローバル変数の広範な使用でした。プログラムの状態が不整合になったり、値が誤って変更または上書きされたりするリスクが高まるため、これは不適切な形式と見なされます。研究者たちはまた、小数精度がコード全体で一貫して維持されていないという事実についての懸念を表明しました。

男、私はそれらの開発者がグローバル変数を使用していないことを望んでいるに違いない!


6
それは私がしばらくの間持っていた最高の笑いでした。利益のためのクローズドソース開発が悪い理由の真の例であり、グローバル変数がうまくいかなかった良い例です!
Evil Spork、2011

ここで確立されていることは、グローバル変数は軽蔑で見られるということです。ここでは、グローバル変数がコードの真の問題であることを示すものは何もありません。SysTestによると、コードは「通常のソフトウェア設計のベストプラクティスと一貫した方法で記述されていません」が、それでも「確実に一貫したテスト結果が生成される」とのことです。したがって、グローバルからの害は実際に文書化されていません。私がそれを見ると、彼らは「まあ、これらの開発者は他の主流世界と同じコーディング宗教を実践していません」と確立しました。
LionKimbro

17

私はこの質問に別の質問で答えます:singeltonsを使用していますか/ singeltonsは悪いですか?

(ほとんどすべての)singeltonの使用法は栄光のグローバル変数だからです。


11
「シングルトンの代わりにグローバルと呼ぶのは悪いことだ」とスマートコメントを投稿しようとしていましたが、私はそれに負けました。
smo 2009年

私はまだ地獄のシングルトンがLOLであるものを理解しようとしています。
GeoffreyF67

1
@Geoffrey:ここではいくつかの良いSO記述がある- stackoverflow.com/questions/11831/...といくつかの良いリンクについて:stackoverflow.com/questions/11831/...
ギャビン・ミラー

10
記録のために、シングルトンは、正当なように聞こえるように栄光のあるDesign Patterns(tm)(lol)の名前を持つグローバル変数です。同じ理由でそれは同様に悪いです。
R .. GitHub ICEのヘルプの停止

@GavinMillerシンプトンを使用しても問題ないと言っています...おっと、シングルトンの片思い
ファンメンデス

14

問題は、それらが悪いことではなく危険なことです。彼らには独自の長所と短所があり、特定のタスクを達成するための最も効率的な方法または唯一の方法である場合があります。ただし、常に適切に使用するための手順を踏んでも、誤用が非常に簡単です。

いくつかの長所:

  • 任意の関数からアクセスできます。
  • 複数のスレッドからアクセスできます。
  • プログラムが終了するまで、範囲外になることはありません。

いくつかの短所:

  • パラメータとして明示的にドラッグしたり、ドキュメント化したりする必要なく、任意の関数からアクセスできます。
  • スレッドセーフではありません。
  • これを防ぐための対策が講じられていない限り、グローバル名前空間を汚染し、名前の衝突を引き起こす可能性があります。

もしそうなら、私がリストした最初の2つの長所と最初の2つの短所はまったく異なるものですが、言葉遣いが異なります。これは、グローバル変数の機能が実際に役立つ可能性があるためです。しかし、それらを有用にする機能そのものが、すべての問題の原因となっています。

一部の問題に対するいくつかの潜在的な解決策:

  • それらが実際に問題の最善または最も効率的な解決策であるかどうかを検討してください。ある場合は任意のより良い解決策は、代わりにそれを使用。
  • 名前空間[C ++]またはシングルトン構造体[C、C ++]に一意の名前(Globalsまたはの良い例がGlobalVars)で配置するか、グローバル変数に標準化された命名規則を使用します(global_[name]またはなどg_module_varNameStyle(コメントのunderscore_dで言及) ))。これにより、その使用法が文書化され(名前空間/構造体の名前を検索してグローバル変数を使用するコードを見つけることができます)、グローバル名前空間への影響を最小限に抑えることができます。
  • グローバル変数にアクセスする関数については、どの変数を読み取り、どの変数を書き込むかを明示的に文書化します。これにより、トラブルシューティングが容易になります。
  • それらを独自のソースファイルに入れextern、関連するヘッダーで宣言することで、それらの使用を、それらにアクセスする必要があるコンパイルユニットに限定することができます。コードが多くのグローバル変数に依存しているが、各コンパイルユニットはそれらのほんの一部にアクセスするだけでよい場合は、それらを複数のソースファイルにソートすることを検討できます。そのため、各ファイルのグローバル変数へのアクセスを制限する方が簡単です。
  • それらをロックおよびロック解除するメカニズムをセットアップし、および/または実際にグローバル変数を変更する必要がある関数をできるだけ少なくするようにコードを設計します。スレッドの競合は依然としてマルチスレッドプログラムで問題を引き起こす可能性がありますが、それらを読み取ることはそれらを書き込むことよりもはるかに安全です。
  • 基本的に、それらへのアクセスを最小化し、名前の一意性を最大化します。名前の衝突を避け、特定の変数を変更する可能性のある関数をできるだけ少なくしたいとします。

それらが良いか悪いかはあなたがそれらをどのように使うかにかかっています。大多数はそれらを悪用する傾向があり、それゆえそれらに対する一般的な警戒心です。適切に使用すれば、それらは大きな恩恵になる可能性があります。悪い使用している場合、しかし、彼らがすることができますあなたを噛まないように戻ってきたとき、あなたは少なくともそれを期待しますか。

それを見る良い方法は、それら自体は悪くないが、悪いデザインを可能にし、悪いデザインの影響を指数関数的に増加させることができるということです。


それらを使用するつもりがない場合でも、安全に使用する方法がわからないため、それらを使用しないよりも、安全に使用する方法を理解し、使用しないことをお勧めします。グローバル変数に依存する既存のコードを維持する必要がある状況に遭遇した場合、それらを適切に使用する方法を知らないと、困難に陥る可能性があります。


1
実用主義のための+1。シングルトンは多くの場合、ボイラープレートを追加してインスタンスを作成し、メンバーにリファクタリングするだけで、グローバル変数になり、別の名前で偽装するだけです。単なる技術的なことでグローバルズの罪を回避する以外に、なぜわざわざ?名前空間は障壁としてはいいですが、シンプルでg_module_varNameStyle完全に読みやすいと思います。明確にするために、グローバルを簡単に回避できる場合はキーワードを簡単に使用します。キーワードは簡単です。なぜなら、回避する必要がある、または難読化する必要があるとは信じられなくなったためです。コードは(衝撃!)はるかに整然としています
underscore_d

@underscore_d主に、変数がグローバル変数であるかローカル変数であるかについての混乱を防ぐことを目的として、グローバル変数とローカル変数をより簡単に区別し、コードを検索するときにグローバル変数を見つけやすくする方法があります。パラメータ/メンバー/など。あなたのような標準の命名規則は、それが一貫している限り、同様に機能します。標準の命名規則のアイデアで私の回答を編集していただき、ありがとうございます。
ジャスティン時間-モニカを

1
「任意の関数について...どの変数を明示的に文書化する」-これは推移的な関係であることを覚えておいてください。関数Aが関数BとCを呼び出す場合、関数Aは両方によって書き込まれた変数(およびその本体に直接含まれる変数)を読み書きします
Caleth

11

別のスレッドで誰かが言ったように(言い換えれば)、「このようなルールは、そうすることの結果を完全に理解するまで破られるべきではありません。」

グローバル変数が必要な場合、または少なくとも非常に役立つ場合があります(たとえば、システム定義のコールバックでの作業)。一方、あなたが言われたすべての理由のためにそれらはまた非常に危険です。

おそらくエキスパートに任せるべきプログラミングの多くの側面があります。時々あなたは非常に鋭いナイフが必要です。しかし、準備が整うまでは使用できません...


1
結果を理解していれば、規則を破っても大丈夫ですが、頻繁にそれを実行していると、何かがおかしくなっています
Juan Mendes

9

特に他の人が同じコードで作業していて、変数が参照されているすべての場所を検索するのに20分を費やしたくない場合は、グローバル変数は一般に悪いです。また、変数を変更するスレッドを追加すると、まったく新しいレベルの頭痛が生じます。

単一の翻訳単位で使用される匿名の名前空間のグローバル定数は、プロのアプリやライブラリでは細かく、どこにでも存在します。ただし、データが変更可能である場合や、複数のTU間でデータを共有する必要がある場合は、データをカプセル化することをお勧めします。これは、設計のためではなく、コードのデバッグや作業のためです。


9

グローバル変数の使用は、じゅうたんの下の汚れを掃除するようなものです。それは迅速な修正であり、短期的には、ダストパンや掃除機で掃除するよりもはるかに簡単です。ただし、後で敷物を移動してしまうと、その下に大きな驚きが生じます。


コンテキストのない怠惰なメタファー!=回答
underscore_d

1
@underscore_d:同意しません。これは(おそらく年齢が原因で)タグが付けられていなくても、ディスカッションの質問です。そのため、このような回答は完全に有効であり、OPの質問に対処することが重要です。
gariepy

7

ローカル変数のみを変更する必要があるプログラムの側面を操作できる場合、グローバル変数は不適切です。OOPでは、グローバルはしばしばカプセル化のアイデアと競合します。


7

あなたの教授は悪い癖を始める前に止めようとしていると思います。

グローバル変数には場所があり、多くの人が言ったように、いつどこで使用するかを知ることは複雑になる場合があります。したがって、教授が禁止することを決定したグローバル変数の理由、方法、時期、および場所についての骨の折れるものに入るのではなく、誰が知っている、彼は将来的にそれらを禁止しないかもしれません。


7

絶対違う。しかし、それらを誤用する...それは悪いです。

ために不注意にそれらを削除するのはそれだけです... 長所と短所を知らない限り、教えられた/学んだように、明確に舵を切り、行動するのが最善ですが、グローバル変数に暗黙の問題はありません。あなたが長所と短所を理解するときは、あなた自身の決断をする方が良いです。


3
-1グローバル変数に対して警告する理由は数多くあります。私にとって最大の理由は、非表示の依存関係とグローバルにより、予測可能な方法でコードをテストすることが非常に困難になることです。自動化された方法でコードをテストする機能を高く評価しない限り、グローバル変数によって痛みが生じるだけであることをお勧めします。さらに、よく構造化されたプログラムには常に代替案があります。
jkp

1
あなたが言っているのは大規模な一般化です、グローバル状態を注意深く使用しても自動テストは妨げられません-実際、ほとんどすべてのアプリはグローバル状態を持っています。概念的には違いはありませんが、依存関係は依然として存在します-それはそれらがどのようにエンコードされるかについてです。
jheriko

1
丁度。彼らは基本的に「壊れやすい」ので、それほど「悪い」わけではありません。何も壊さずにそれらを使用する方法と、代替の代わりにそれらを使用するタイミングを知っている場合、それらは役に立ちます。そうでなければ...それほどではありません。
ジャスティン時間-モニカ

4

グローバル変数は小さなプログラムでは問題ありませんが、大きなプログラムで同じように使用すると恐ろしいです。

つまり、学習しながらそれらを使用する習慣を簡単に身に付けることができます。これは、教授があなたを守ろうとしていることです。

あなたがより経験を積んでいるとき、彼らが大丈夫であるとき、それは学ぶのがより簡単になるでしょう。


4

いいえ、まったく悪くはありません。この決定を行うには、コンパイラによって生成された(マシン)コードを調べる必要があります。グローバルよりローカルを使用する方がはるかに悪い場合があります。また、ローカル変数に「静的」を置くと、基本的にグローバルになります(そして、実際のグローバルが解決する他の醜い問題が発生します)。「ローカルグローバル」は特に悪い。

グローバルを使用すると、メモリ使用量をクリーンに制御できます。これは、ローカルで行うのがはるかに難しいことです。最近では、メモリが非常に限られている組み込み環境でのみ問題になります。組み込みが他の環境と同じであり、プログラミングルールが全体で同じであると想定する前に知っておくべきこと。

あなたが教えられているルールに疑問を呈するのは良いことです、それらのほとんどはあなたが言われている理由のためではありません。ただし、最も重要な教訓は、これは永遠に持ち運ぶためのルールであるということではありませんが、このクラスに合格して前進するために遵守する必要があるルールです。実生活では、XYZ社の場合、給料を受け取り続けるために最終的に尊重しなければならない他のプログラミングルールがあることがわかります。どちらの状況でもルールを議論することができますが、私はあなたが学校よりも仕事ではるかに幸運になると思います。あなたは多くの学生のほんの1人であり、あなたの席はすぐに交換されます、教授はしません、あなたはこの製品を最後まで見る必要があるプレーヤーの小さなチームの1人であり、その環境で開発されたルールはチームメンバーだけでなく、製品と会社の利益 誰もが気にされている場合、または特定の製品について、大学で学んだことや一般的なプログラミングに関する本に違反するエンジニアリング上の理由がある場合は、チームにそのアイデアを売り、有効な方法として書き留めてください。 。すべてが現実の世界では公正なゲームです。

学校や本で教えられているすべてのプログラミング規則に従えば、プログラミングのキャリアは非常に制限されます。あなたはおそらく生き残り、実りあるキャリアを持つことができますが、あなたが利用できる環境の幅と幅は非常に制限されます。ルールが存在する理由と理由を理解し、それを守ることができるのであれば、それは良いことです。もしあなたの理由が「私の先生がそう言ったから」であるなら、それはあまり良くありません。

このようなトピックは職場で議論されることが多く、コンパイラとプロセッサ(および言語)が進化するにつれ、今後もそうなるでしょう。そのため、この種のルールを守り、自分の立場を守ったり、おそらく他の意見を持つ誰かからレッスンを受けたりしないでください。前進する。

それまでの間、最も大きな声で話すか、最大のスティックを運ぶ人が言うことをすべて実行します(あなたが最も大きな声で叫び、最大のスティックを運ぶような時まで)。


4
これは、「IBMを購入したことで解雇されたことはない」という別の言い方ですか?
ゴードンポッター

1
グローバル変数を使用する一部のアプリケーションでは、実際に作業が簡単になるという利点があります。一般に、グローバル変数の使用は、ソースのセクション間の結合の隠れた経路に関する問題の原因です。ただし、グローバルとして参照される共有メモリ領域を持つことは、デバイスインターフェイスや、さまざまな種類の定数またはジャンプテーブルを含むグローバルパラメータテーブルなどの実装に使用されます。
Richard Chambers 14

4

このスレッド全体でマルチスレッド化自体が困難または不可能になるという点に反対したいと思います。グローバル変数は状態を共有しますが、グローバルの代替手段(ポインターの受け渡しなど)も状態を共有する場合があります。マルチスレッドの問題は、共有状態がグローバル変数などで共有されているかどうかではなく、共有状態を適切に使用する方法です。

ほとんどの場合、マルチスレッドを実行するときには、何かを共有する必要があります。たとえば、プロデューサー/コンシューマーパターンでは、作業単位を含むスレッドセーフキューを共有する場合があります。そして、そのデータ構造はスレッドセーフなので、共有することができます。そのキューがグローバルであるかどうかは、スレッドセーフに関してはまったく関係ありません。

グローバルを使用しない場合は、プログラムをシングルスレッドからマルチスレッドに変換する方が簡単であるという、このスレッド全体で示されている暗黙の希望。はい、グローバルを使用すると、足元で自分を簡単に撃つことができますが、自分を撃つ方法はたくさんあります。

他の点がまだ残っているので、私はグローバルを主張していません。私のポイントは、プログラム内のスレッドの数は変数のスコープとは何の関係もないということです。


3

はい、無能なプログラマにそれらを使用させた場合(特に科学者の90%を読む)、20以上のファイルに600以上のグローバル変数が広がり、80%の関数がvoidを取り、voidを返し、操作する12,000行のプロジェクトが発生します。完全にグローバルな状態。

プロジェクト全体を知らないと、ある時点で何が起こっているのかをすぐに理解することができなくなります。


2

グローバル変数の使用は、実際には要件によって異なります。その利点は、値を繰り返し渡すオーバーヘッドを削減できることです。

ただし、セキュリティ上の問題が発生するため、教授は正しいので、グローバル変数の使用はできるだけ避けてください。グローバル変数は、デバッグ困難な場合がある問題も作成します 。

例えば:-

実行時に変数値が変更される状況。その瞬間、コードのどの部分がそれを変更しているか、どのような条件であるかを特定することは困難です。


2

構成に関しては、グローバルが適しています。私たちがしたいときに設定を/変更持っている世界的な影響プロジェクト全体を

したがって、1つの構成を変更することができ、変更プロジェクト全体に向けられます。しかし、私はあなたがグローバルを使うには非常に賢くなければならないだろうと警告しなければなりません。


1

遅かれ早かれ、その変数がどのように設定されるか、またはそれがアクセスされたときに何が起こるかを変更する必要があるでしょう。

グローバル変数を持たない方が実際には常に優れています。dam getおよびsetメソッドを記述し、1日、1週間、または1か月後にそれらが必要になったときに気を配ってください。


1

私は通常、シングルトンや動的に読み込まれるライブラリ内の関数への関数ポインターなど、めったに変更されない値にグローバルを使用します。マルチスレッドアプリケーションで可変グローバルを使用すると、バグの追跡が困難になる傾向があるため、これは原則として回避するようにします。

多くの場合、引数を渡す代わりにグローバルを使用する方が高速ですが、今日よく使用するマルチスレッドアプリケーションを作成している場合、通常はうまく機能しません(スレッドスタティックを使用できますが、パフォーマンスの向上には疑問があります)。 。


1

enterprize内のWebアプリケーションでは、最適化の理由でサーバー上にセッション/ウィンドウ/スレッド/ユーザー固有のデータを保持し、接続が不安定な作業の損失を防ぐために使用できます。前述のように、競合状態を処理する必要があります。この情報にはクラスの単一のインスタンスを使用し、慎重に管理されます。


1

結局のところ、プログラムまたはアプリは引き続き機能しますが、整理されていて、何が起こっているのかを完全に理解することが重要です。すべての関数で変数値を共有すると、値を変更している関数を追跡することが困難になる場合があります(関数が変更している場合)、100万倍のデバッグが困難になります。


0

セキュリティとは、変数がglobalと宣言されている場合、誰でも変数を操作できることを意味します。これを説明するために、銀行プログラムにグローバル変数としてバランスがある場合、ユーザー関数がこれを操作できるようになり、銀行の役員も操作できるようになります。これは問題があります。唯一のユーザーに読み取り専用と引き出し機能を与える必要がありますが、銀行の店員はユーザーが個人的に机に現金を与えるときに金額を追加できます。これはそれが機能する方法です


-1

マルチスレッドアプリケーションでは、グローバル変数の代わりにローカル変数を使用して、競合状態を回避します。

複数のスレッドが共有リソースにアクセスし、少なくとも1つのスレッドがデータへの書き込みアクセス権を持つ場合に、競合状態が発生します。その場合、プログラムの結果は予測できず、さまざまなスレッドによるデータへのアクセス順序に依存します。

この詳細については、https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code


後世のために:これは部分的には正しいです。この回答の「ローカル変数」は、OPが参照するより一般的なスコープローカル変数ではなく、スレッドローカル変数を指します。スレッドに対して安全でない方法でグローバル変数を変更することの副作用は、並行していない方法でグローバル状態を変更することの副作用とは大きく異なります。
Jules
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.