286

C / C ++では、グローバル変数は私の教授が思っているほど悪いものですか?

4

28 に答える 28

306

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

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

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

于 2009-01-27T20:11:27.710 に答える
113

重要なことは、全体的な目標を覚えておくことです。明確さ

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

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

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

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

于 2010-02-24T12:19:03.677 に答える
69

私の教授は、次のようなことを言っていました。グローバル変数を正しく使用すれば、グローバル変数を使用しても問題ありません。正しく使うのが苦手だったので、めったに使いませんでした。

于 2009-01-27T18:42:22.507 に答える
47

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

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

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

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

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

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

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

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

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

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

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

C++namespaceと C のstruct技法の使用

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

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

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

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

于 2014-07-01T02:10:43.013 に答える
39

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

そうです、状況の 90% でグローバル変数が悪いのです。例外は、大学時代に見られる可能性は低いです。私が思いつく例外の 1 つは、割り込みテーブルなどの本質的にグローバルなオブジェクトを処理することです。DB 接続などはグローバルに見えますが、そうではありません。

于 2009-01-27T20:22:33.333 に答える
22

はい。ただし、グローバル変数を使用するコードでの作業を停止し、グローバル変数を使用するコードを使用する別の記述を開始するまで、グローバル変数のコストは発生しません。しかし、コストはまだそこにあります。

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

于 2009-01-27T18:37:41.067 に答える
22

グローバル変数は、作成するのと同じくらい悪いものです。

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

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

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

正しく使用すれば、Gotosもそうではありません。

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

于 2009-01-27T18:44:00.913 に答える
20

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

この記事を参照してください: バグのある飲酒コードはソースレビューの重要性を反映しています

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

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

于 2009-05-16T23:01:56.360 に答える
17

私は別の質問でこの質問に答えます:あなたはsingeltonsを使いますか/ singeltonsは悪いですか?

(ほとんどすべての)単一の使用法は、栄光に満ちたグローバル変数だからです。

于 2009-01-27T18:46:46.540 に答える
11

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

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

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

于 2009-01-27T20:22:36.127 に答える
10

グローバル変数を使用することは、じゅうたんの下の汚れを一掃するようなものです。ちりとりや掃除機で掃除するよりも、短期間で簡単に解決できます。ただし、後でラグを移動すると、下に大きな混乱が生じることになります.

于 2009-01-27T20:44:37.720 に答える
9

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

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

于 2009-01-27T20:10:46.120 に答える
8

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

于 2009-01-27T18:39:13.700 に答える
7

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

目的のためにそれらを無意識に削除することはそれだけです...無意味です。長所と短所を知らない限り、教えられた/学んだように明確に操縦して実行するのが最善ですが、グローバル変数に暗黙的に問題はありません。あなたが賛否両論を理解するとき、あなた自身の決定をよりよくしてください。

于 2009-03-06T13:19:25.837 に答える
7

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

グローバル変数にはそれぞれの役割があり、多くの人が言うように、グローバル変数をいつどこで使用するかを知るのは複雑な場合があります。だから私は、なぜ、どのように、いつ、どこであなたの教授がグローバル変数を禁止することに決めたのかという核心に立ち入るのではなく、. 誰が知っているか、彼は将来それらの禁止を解除するかもしれません.

于 2009-01-27T20:02:14.500 に答える
5

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

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

于 2012-02-04T08:22:11.790 に答える
5

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

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

教えられているルールに疑問を抱くのは良いことです。それらのほとんどは、あなたが教えられている理由によるものではありません。ただし、最も重要な教訓は、これが永遠に持ち歩くルールではなく、このクラスに合格して前進するために尊重する必要があるルールであるということです。人生において、会社 XYZ には、給与を受け取り続けるために最終的に尊重しなければならない他のプログラミング規則があることに気付くでしょう。どちらの状況でもルールについて議論することはできますが、学校よりも仕事の方がはるかに幸運に恵まれると思います。あなたは多くの学生の 1 人にすぎません。あなたの席はすぐに入れ替わりますが、教授はそうではありません。あなたは仕事で、この製品を最後まで見なければならないプレーヤーの小さなチームの 1 人であり、その環境で開発されたルールは、チームメンバーだけでなく、製品と会社の利益、したがって、誰もが同じ考えを持っている場合、または特定の製品について、大学で学んだことや汎用プログラミングに関する本に違反する十分な技術的理由がある場合は、チームにアイデアを売り込み、推奨される方法ではない場合でも有効な方法として書き留めます。 . 現実の世界ではすべてが公正なゲームです。

学校や本で教えられているプログラミングのルールをすべて守っていると、プログラミングのキャリアは非常に限られてきます。あなたはおそらく生き残り、実りあるキャリアを積むことができますが、あなたが利用できる環境の幅と幅は非常に限られています. ルールが存在する方法と理由を知っていて、それを守ることができれば、それは良いことですが、「先生がそう言ったから」という理由だけであれば、それはあまり良くありません。

このようなトピックは職場でよく議論され、今後も議論され続けることに注意してください。コンパイラとプロセッサ (および言語) が進化するにつれて、このような種類の規則も同様に進化し、自分の立場を擁護したり、別の意見を持つ人から教訓を教わったりすることはありません。前進します。

それまでの間は、最も大きな声で話す人や、最も大きな棒を持っている人の言うことを何でも実行してください (あなたが最も大きな声で叫び、最も大きな棒を持っている人になるまで)。

于 2009-01-28T16:39:38.307 に答える
4

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

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

あなたがより経験を積むと、彼らが大丈夫なときに学ぶのがより簡単になります.

于 2009-01-27T20:16:13.613 に答える
3

グローバルは、構成に関しては優れています。構成/変更プロジェクト全体にグローバルな影響を与えるようにしたい場合。

したがって、 1 つの構成を変更すると、その変更はプロジェクト全体に向けられます。ただし、 globals を使用するには非常に賢くなければならないことを警告しなければなりません。

于 2017-02-19T08:33:17.610 に答える
1

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

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

于 2011-07-12T09:18:02.470 に答える
1

遅かれ早かれ、変数の設定方法や変数へのアクセス時に何が起こるかを変更する必要があるか、変数がどこで変更されたかを突き止める必要があります。

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

于 2009-01-27T20:28:08.160 に答える
-1

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

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

詳細はこちらhttps://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code

于 2014-09-07T09:47:52.270 に答える
-1

security is less means any one can manipulate the variables if they are declared global , for this one to explain take this example if you have balance as a global variable in your bank program the user function can manipulate this as well as bank officer can also manipulate this so there is a problem .only user should be given the read only and withdraw function but the clerk of the bank can add the amount when the user personally gives the cash in the desk.this is the way it works

于 2012-11-23T07:34:12.837 に答える