web-dev-qa-db-ja.com

変数を初期化することの重要性

変数を初期化することはどのくらい重要ですか?

適切な初期化により、メモリリークが回避されたり、パフォーマンスが向上したりしますか?

9
Vivek

初期化されていない変数は、プログラムを非決定性にします。プログラムが実行されるたびに、動作が異なる場合があります。動作環境、時刻、月の位相、およびそれらの順列への無関係な変更は、これらのデーモンがいつどのように出現するかに影響します。プログラムは、欠陥が発生する前に100万回実行される場合もあれば、毎回実行される場合もあれば、100万回実行される場合もあります。多くの問題は「不具合」に分類されて無視されるか、顧客からの欠陥レポートが「再現不能」としてクローズされました。問題を「修正」するためにマシンをどのくらいの頻度で再起動しましたか?どのくらいの頻度でお客様に「それが起こったのを見たことがない、もう一度見た場合はお知らせください」と言ったことはありませんか。

欠陥の再現はテスト環境ではほとんど不可能であるため、発見して修正することはほとんど不可能です。

一般に、信頼性が高く安定していると考えられるコードでは、バグが表面化するまでに数年かかる場合があります。欠陥はより最近のコードにあると推定されます-それを追跡するのにかなり長い時間がかかります。コンパイラの変更、コンパイラスイッチ、コード行の追加でさえ、動作を変更する可能性があります。

変数を初期化することは、正しく機能するプログラムがそうでないプログラムよりも無限大であるというだけでなく、開発者がそこにあるはずのない欠陥を見つけて修正するのに費やす時間を減らし、「実際の」作業を行うのに多くの時間を費やすという、大きなパフォーマンス上の利点があります。

変数を初期化することのその他の重要な利点は、コードの元の作成者が変数を何に初期化するかを決定する必要があることです。これは常に些細なことではなく、些細なことではない場合は、設計が悪いことを示している可能性があります。

メモリリークは別の問題ですが、適切な初期化はそれらを防止するのに役立つだけでなく、それらを検出してソースを見つけるのにも役立ちます-これは非常に言語に依存しているので、これは、私が提供できるよりもさらに調査する価値のある別個の質問ですこの答えで。

編集:一部の言語(C#など)では、初期化されていない変数を使用することはできません。プログラムがコンパイルされなかったり、実行時にエラーが報告されたりするためです。ただし、これらの特性を持つ多くの言語には潜在的に安全でないコードへのインターフェースがあるため、そのようなインターフェースを使用するときは、初期化されていない変数を導入しないように注意する必要があります。

7
mattnz

Telastynが指摘したように変数を初期化すると、バグを防ぐことができます。変数が参照型の場合、変数を初期化することで、後のnull参照エラーを防止できます。

Null以外のデフォルトを持つ任意のタイプの変数は、デフォルト値を格納するためにメモリを消費します。

7
Kevin

初期化されていない変数を使用しようとすると常にバグになるため、そのバグが発生する可能性を最小限に抑えることは理にかなっています。

おそらく、問題を緩和するためにプログラミング言語がとる最も一般的なアプローチは、自動的にデフォルト値に初期化することです。そのため、少なくとも変数を初期化し忘れた場合は、0ではなく0x16615c4bになります。

とにかくゼロに初期化された変数が必要になった場合、これはバグの大部分を解決します。ただし、誤った値に初期化された変数を使用することは、まったく初期化されていない変数を使用するのと同じくらい悪いことです。実際、エラーはより微妙で検出が困難な場合があるため、さらに悪化する場合もあります。

関数型プログラミング言語は、初期化されていない値を許可しないだけでなく、再割り当てを完全に禁止することによってこの問題を解決します。これで問題が解消され、思ったほど制限が厳しくないことがわかります。非関数型言語であっても、初期化するための正しい値が得られるまで変数を宣言するのを待つと、コードははるかに堅牢になる傾向があります。

パフォーマンスに関する限り、それはおそらく無視できます。初期化されていない変数では、最悪の場合、割り当てが1つ増え、必要以上に長くメモリを占有します。優れたコンパイラは、多くの場合、違いを最適化できます。

メモリリークはまったく関係ありませんが、適切に初期化された変数はより短い期間スコープに入る傾向があるため、プログラマーが誤ってリークする可能性は少し低くなります。

6
Karl Bielefeldt

初期化は、初期値が重要であることを意味します。初期値が重要な場合は、はい、明らかに、初期化されていることを確認する必要があります。それが問題ではない場合、それは後で初期化されることを意味します。

不要な初期化により、無駄なCPUサイクルが発生します。これらの無駄なサイクルは特定のプログラムでは問題にならない場合がありますが、他のプログラムでは、速度が主な関心事であるため、すべてのサイクルが重要です。したがって、パフォーマンスの目標を理解し、変数を初期化する必要があるかどうかを理解することが非常に重要です。

メモリリークは完全に異なる問題であり、通常、メモリアロケータ機能がメモリブロックを発行し、後でリサイクルします。郵便局を考えてみてください。あなたは行って郵便受けを求めます。彼らはあなたに1つを与えます。あなたは別のものを求めます。彼らはあなたに別のものを与えます。ルールは、あなたがそれを返す必要があるメールボックスを使い終わったときであるということです。あなたがそれを返すのを忘れた場合、彼らはまだあなたがそれを持っていると考え、箱は他の人が再利用することはできません。そのため、使用されていないメモリのチャンクが拘束されており、これがメモリリークと呼ばれています。ある時点でボックスを要求し続けると、メモリが不足します。これを単純化しすぎましたが、これが基本的な考え方です。

5
Elliptical view

他の人が言ったように、それは言語に依存します。しかし、変数の初期化に関するJava(および効果的なJava)のアイデアを示します。これらは、他の多くの高水準言語で使用できるはずです。

定数とクラス変数

クラス変数-Javaでstaticとマークされています-これらは定数のようなものです。これらの変数は通常、最終的なものであり、=を使用して定義した直後、またはクラス初期化子内から初期化する必要がありますブロックstatic { // initialize here }

田畑

多くの上位レベルおよびスクリプト言語と同様に、フィールドには自動的にデフォルト値が割り当てられます。数値とcharの場合、これはゼロ値になります。文字列およびその他のオブジェクトの場合、nullになります。現在、nullは危険であり、慎重に使用する必要があります。したがって、これらのフィールドはできるだけ早く有効な値に設定する必要があります。通常、コンストラクターはこれに最適な場所です。変数がコンストラクター中に設定され、後で変更されないことを確認するには、finalキーワードを使用して変数にマークを付けることができます。

nullをある種のフラグまたは特別な値として使用したいという衝動に抵抗してください。たとえば、状態を保持する特定のフィールドを含めます。 state列挙の値を使用するStateという名前のフィールドが適切な選択です。

メソッドパラメータ

パラメータの値への変更(オブジェクトまたは整数などの基本的な型への参照)は呼び出し元からは認識されないため、パラメータはfinalとしてマークする必要があります。つまり、変数自体の値は変更できません。 mutableオブジェクトインスタンスcanの値は変更できますが、参照を変更して別のオブジェクトまたはnullを指すようにすることはできません。

ローカル変数

ローカル変数は自動的に初期化されません。値を使用する前に初期化する必要があります。変数が確実に初期化されるようにする1つの方法は、変数をある種のデフォルト値に直接初期化することです。ただし、これはnotを実行する必要があります。ほとんどの場合、デフォルト値は期待した値ではありません。

変数が必要な場所でのみ変数を正確に定義する方がはるかに優れています。変数が単一の値のみを取る場合(これは適切なコードのほとんどの変数に当てはまります)、変数finalをマークできます。これにより、ローカル変数が確実に1回だけ割り当てられ、0回または2回ではありません。例:

public static doMethod(final int x) {
    final int y; // no assignment yet, it's final so it *must* be assigned
    if (x < 0) {
        y = 0;
    } else if (x > 0) {
        y = x;
    } else {
        // do nothing <- error, y not assigned if x = 0
        // throwing an exception here is acceptable though
    }
}

変数が使用前に初期化されていない場合、多くの言語で警告が表示されることに注意してください。言語仕様とフォーラムをチェックして、不必要に心配しないかどうかを確認してください。

2
Maarten Bodewes

変数の初期化を解除しても問題はありません。

問題は、まだ書き込まれていない変数を読み取るときだけです。

コンパイラや変数の種類によっては、アプリケーションの起動時に初期化が実行されます。か否か。

自動初期化に依存しないのが一般的な使用法です。

1
mouviciel

変数の初期化(暗黙的または明示的)は重要です。変数を初期化しないと、常にエラーになります(ただし、暗黙的に初期化される場合があります。以下を参照してください)。 C#コンパイラなどの最新のコンパイラは(例として)、これをエラーとして扱い、コードを実行させません。初期化されていない変数は、単に役に立たず、有害です。乱数ジェネレータを作成しているのでない限り、コードの一部から確定的で再現可能な結果が生成されることが期待されます。これは、初期化された変数の操作を開始した場合にのみ達成できます。

本当に興味深い質問は、変数が自動的に初期化されるかどうか、または手動で初期化する必要があるかどうかです。使用する言語によって異なります。たとえば、C#では、フィールド、つまりクラスレベルの「変数」は常に、その変数の型default(T)のデフォルト値に自動的に初期化されます。この値は、すべてゼロで構成されるビットパターンに対応します。これは言語仕様の一部であり、言語の実装の技術的な詳細だけではありません。したがって、安全に信頼できます。 言語仕様で暗黙的に初期化されることが明記されている場合に限り、変数を明示的に初期化しない方が安全です。別の値が必要な場合は、変数を明示的に初期化する必要があります。しかしながら; C#では、ローカル変数、つまりメソッドで宣言された変数はnotで自動的に初期化され、常に変数を明示的に初期化する必要があります。