変数を初期化することはどのくらい重要ですか?
適切に初期化することでメモリリークを回避できますか、それともパフォーマンス上の利点がありますか
null
一般的なコンパイラによって0(または)に初期化されますが、リリース用にコンパイルするとランダムなガベージになります。(私のC ++の知識は約10年前のものですが、状況は変わった可能性があります)
変数を初期化することはどのくらい重要ですか?
適切に初期化することでメモリリークを回避できますか、それともパフォーマンス上の利点がありますか
null
一般的なコンパイラによって0(または)に初期化されますが、リリース用にコンパイルするとランダムなガベージになります。(私のC ++の知識は約10年前のものですが、状況は変わった可能性があります)
回答:
初期化されていない変数は、プログラムを非決定性にします。プログラムが実行されるたびに、動作が異なる場合があります。動作環境、時刻、月の位相、およびそれらの順列への無関係な変更は、これらのデーモンがいつどのように出現するかに影響します。プログラムは、欠陥が発生する前に100万回実行される場合もあれば、毎回実行される場合もあれば、100万回実行される場合もあります。多くの問題は「不具合」に分類されて無視されるか、顧客からの欠陥レポートが「再現不能」としてクローズされました。問題を「修正」するためにマシンをどのくらいの頻度で再起動しましたか?どのくらいの頻度でお客様に「それが起こったことは一度も見たことがないので、もう一度見た場合はお知らせください」と言ったことはありませんか。
欠陥の再現はテスト環境ではほとんど不可能であるため、発見して修正することはほぼ不可能です。
一般に、信頼性が高く安定していると考えられるコードでは、バグが表面化するまでに数年かかる場合があります。欠陥はより最近のコードにあると推定されます-それを追跡するのにかなり長い時間がかかる場合があります。コンパイラの変更、コンパイラスイッチ、さらにはコード行を追加するだけでも、動作が変わる可能性があります。
変数を初期化することは、正しく機能するプログラムがそうでないプログラムよりも無限に速いというだけでなく、開発者がそこにあるはずのない欠陥を見つけて修正するのに費やす時間を減らし、「実際の」作業を行う時間を増やすという、大きなパフォーマンス上の利点があります。
変数を初期化する他の重要な利点は、コードの元の作成者が初期化する対象を決定する必要があることです。これは常に些細なことではなく、些細なことではない場合は、設計が悪いことを示している可能性があります。
メモリリークは別の問題ですが、適切な初期化はそれらを防ぐのに役立つだけでなく、それらを検出してソースを見つけるのにも役立ちます-これは非常に言語に依存します。この答えで。
編集:一部の言語(C#など)では、初期化されていない変数を使用することはできません。プログラムがコンパイルされなかったり、実行時にエラーが報告されたりするためです。ただし、これらの特性を持つ多くの言語には潜在的に安全でないコードへのインターフェースがあるため、そのようなインターフェースを使用する場合は、初期化されていない変数を導入しないように注意する必要があります。
初期化されていない変数を使用しようとすることは常にバグであるため、そのバグが発生する可能性を最小限に抑えることは理にかなっています。
おそらく、問題を緩和するためにプログラミング言語が取る最も一般的なアプローチは、自動的にデフォルト値に初期化することです。そのため、少なくとも変数を初期化し忘れた場合は、のようなものでは0
なく、のようなものになり0x16615c4b
ます。
とにかくゼロに初期化された変数が必要になった場合、これはバグの大部分を解決します。ただし、誤った値に初期化された変数を使用することは、まったく初期化されなかった変数を使用するのと同じくらい悪いことです。実際、エラーはより微妙で検出が困難な場合があるため、さらに悪化する場合もあります。
関数型プログラミング言語は、初期化されていない値を許可しないだけでなく、再割り当てを完全に禁止することによってこの問題を解決します。これで問題が解消され、思ったほど制限が厳しくないことがわかります。非関数型言語であっても、初期化する正しい値が得られるまで変数を宣言するのを待つと、コードははるかに堅牢になる傾向があります。
パフォーマンスに関する限り、それはおそらくごくわずかです。最悪の場合、初期化されていない変数では、割り当てが1つ増え、必要以上に長くメモリを占有します。優れたコンパイラは、多くの場合、違いを最適化できます。
メモリリークは完全に無関係ですが、適切に初期化された変数はより短い期間スコープに入る傾向があるため、プログラマーが誤ってリークする可能性は少し低くなります。
初期化は、初期値が重要であることを意味します。初期値が重要な場合は、はい、明らかに、初期化されていることを確認する必要があります。それが問題ではない場合、それは後で初期化されることを意味します。
不要な初期化により、CPUサイクルが浪費されます。これらの無駄なサイクルは特定のプログラムでは問題にならない可能性がありますが、他のプログラムでは、速度が主な関心事であるため、すべての単一サイクルが重要です。したがって、パフォーマンスの目標を理解し、変数を初期化する必要があるかどうかを理解することが非常に重要です。
メモリリークは完全に異なる問題であり、通常はメモリアロケータ関数がメモリブロックを発行して後でリサイクルする必要があります。郵便局を考えてみてください。あなたは行って郵便受けを求めます。彼らはあなたに1つを与えます。あなたは別のものを求めます。彼らはあなたに別のものを与えます。ルールは、あなたがそれを返す必要があるメールボックスを使い終わったときであるということです。あなたがそれを返すのを忘れた場合、彼らはまだあなたがそれを持っていると考え、箱は他の人が再利用することはできません。そのため、使用されていないメモリのチャンクが拘束されており、これがメモリリークと呼ばれています。ある時点でボックスを要求し続けると、メモリが不足します。これを単純化しすぎましたが、これが基本的な考え方です。
他の人が言ったように、それは言語に依存します。ただし、変数の初期化に関するJava(および効果的なJava)のアイデアを示します。これらは、他の多くの高水準言語で使用できるはずです。
static
Javaでマークされたクラス変数は定数のようなものです。これらの変数は通常、最終であり=
、クラス初期化子ブロックを使用して、またはクラス初期化子ブロック内から定義した直後に初期化する必要がありますstatic { // initialize here }
。
多くの上位レベルおよびスクリプト言語と同様に、フィールドには自動的にデフォルト値が割り当てられます。数値の場合、char
これはゼロ値になります。文字列およびその他のオブジェクトの場合は、になりますnull
。今null
は危険なので、控えめに使用する必要があります。したがって、これらのフィールドはできるだけ早く有効な値に設定する必要があります。通常、コンストラクターはこれに最適な場所です。変数がコンストラクターの間に設定され、後で変更されないことを確認するために、final
キーワードでそれらをマークすることができます。
null
ある種の旗や特別な価値として使用したいという衝動に抵抗してください。たとえば、状態を保持する特定のフィールドを含めることをお勧めします。列挙型state
の値を使用する名前のフィールドがState
適切な選択です。
パラメータの値に対する変更(オブジェクトまたは整数などの基本的な型への参照)は呼び出し元からは認識されないため、パラメータはとしてマークする必要がありますfinal
。つまり、変数自体の値は変更できません。変更可能なオブジェクトインスタンスの値は変更できますが、参照を変更して別のオブジェクトをポイントすることはできませんnull
。
ローカル変数は自動的に初期化されません。値を使用する前に初期化する必要があります。変数が確実に初期化されるようにする1つの方法は、変数をある種のデフォルト値に直接初期化することです。ただし、これは行うべきではありません。ほとんどの場合、デフォルト値は期待した値ではありません。
変数を必要な場所にのみ正確に定義する方がはるかに優れています。変数が単一の値のみを取る場合(これは、適切なコードのほとんどの変数に当てはまります)、変数にマークを付けることができますfinal
。これにより、ローカル変数が0回または2回ではなく、正確に1回割り当てられることが保証されます。例:
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
}
}
変数が使用前に初期化されていない場合、多くの言語で警告が表示されることに注意してください。言語仕様とフォーラムをチェックして、不必要に心配しないかどうかを確認してください。
変数の初期化(暗黙的または明示的)は重要です。変数を初期化しないと、常にエラーになります(ただし、暗黙的に初期化される場合があります。以下を参照してください)。C#コンパイラなどの最新のコンパイラは(例として)、これをエラーとして扱い、コードを実行させません。初期化されていない変数は、単に役に立たず、有害です。乱数ジェネレータを作成しているのでない限り、コードの一部から確定的で再現可能な結果が生成されることが期待されます。これは、初期化された変数の操作を開始した場合にのみ達成できます。
本当に興味深い質問は、変数が自動的に初期化されるのか、それとも手動で行う必要があるのかということです。使用する言語によって異なります。たとえばC#では、クラスレベルの「変数」などのフィールドは、常にその変数の型のデフォルト値に自動的に初期化されますdefault(T)
。この値は、すべてゼロで構成されるビットパターンに対応します。これは言語仕様の一部であり、言語の実装の技術的な詳細だけではありません。したがって、安全に信頼できます。言語仕様で暗黙的に初期化されていると宣言されている場合に限り、変数を明示的に初期化しない方が安全です。別の値が必要な場合は、変数を明示的に初期化する必要があります。しかしながら; C#では、ローカル変数、つまりメソッドで宣言された変数は自動的に初期化されないため、常に変数を明示的に初期化する必要があります。