24

私はこのようなコードをたくさん見てきました:

SomeType* ptr = NULL;
ptr = SomeMethod(some, params);

ポイントは何ですか?私はまた、ptrどこか他の場所で宣言されているのを見てきました (たとえば、クラス定義で)。次に、クラス コンストラクターで次のようになります。

ptr = NULL;
ptr = SomeMethod(some, params);

なぜこれが行われるのかわかりません。さすがにLINEptr = NULLはダメですか?

4

6 に答える 6

34

"SomeMethod" が例外をスローした場合、 SomeType* は、指したくないものを指し続けます。したがって、ポインターが古いものをもう指したくない場合は、ポインターを null に設定することをお勧めします。

于 2013-01-28T19:55:40.447 に答える
16

C++ に適用される例外をスローするという非常に優れた点は別として、C でも、すべての変数を初期化することをお勧めします。コンパイラは、必要がないと判断できる場合、ほぼ常に初期化を最適化します。

そうしないとどうなるかの例を次に示します。

SomeType* ptr;
ptr = SomeMethod(some, params);

ptrご覧のとおり、有効な値がなくても問題なく動作します。

ここで、もう少しコードを追加することをお勧めします。

SomeType* ptr;

int x = someotherfunction;

if (x > 90)
{
     ptr = SomeMethod(some, params);
}

突然、ptrランダムで意味のないコンテンツが表示されます。NULL の可能性もありますが、それ以外の可能性が非常に高くなります。はい、私たちの変更が何か他のものに影響を与えていないかどうかを確認することを忘れないでください. 「おっと、それは考えていませんでした」。

「someotherfunction」を追加した新しいコードが 20 行または 30 行であると想像してみてください。問題がはっきりとわかります。

于 2013-01-28T20:02:41.530 に答える
3

最初のケースでは、新しい値を宣言するときに常に値を割り当てることをお勧めします。これにより、最終的に値が統一されてしまうことがなくなります (自分の間違いから身を守るためです)。ただし、連続している場合は、役に立たないと見なすことができます。

2番目のケースでは、それはまったく役に立ちません。

于 2013-01-28T19:56:23.940 に答える
2

それは実に役に立たない (これは「デッドアサインメント」と呼ばれる)。NULLただし、宣言時にポインターを初期化し、明示的に個別に割り当てることを好む人もいます。おそらく、これは読みやすさの理由によるものです (たとえば、デバッグのために代入がコメントアウトされている場合でも、変数を宣言する方が読みやすいと考える人や、変数を宣言しておくと便利だと考える人もいます)。私はそれをするかどうかわからない/これを練習と見なす.

また、ほとんどのコンパイラは割り当てを自動的に最適化することにも注意してください。

于 2013-01-28T19:56:34.893 に答える
2

この慣行は役に立たないだけではありません。それは有害です。あなたがちょうど書いた場合:

SomeType* ptr = NULL;
/* lots of stuff in between */
ptr = SomeMethod(some, params);

介在するコードのどこかで誤って使用ptrした場合、コンパイラはこのエラーについて通知する方法がありません。あなたが書いた場合:

SomeType* ptr;
/* lots of stuff in between */
ptr = SomeMethod(some, params);

ptr代入の前に を使用すると UB になり、適切なコンパイラまたは静的解析ツールによってこのエラーが通知されます。

于 2013-01-28T21:04:48.067 に答える
1

このコードは現状では役に立ちませんが、将来のメンテナンスで冗長な初期化と代入の間にさらに行が追加され、初期化が冗長でなくなることが予想されます。

コードは、削除の結果である可能性もあります。つまり、宣言と割り当ての間に何らかのコードが存在していた可能性がありますが、その後削除され、割り当てを初期化にマージするためのクリーンアップは行われませんでした。もちろん、コードがそのままであることに意味はありません。この状況では、どのようにしてそのようになったかについての歴史的な説明 (およびおそらくそれを変更する正当化) しかありません。

「使用されていない可能性がある」変数に関するコンパイラの警告を誰かが黙らせなければならなかった結果として、一見無用な変数の初期化が発生することがあります。コンパイラは、すべての場合に変数が代入によって何らかの方法で初期化されることを証明できるほど洗練されていません。

宣言された時点ですべての変数を初期化することは、初期化されていないデータの結果として予測できない動作が発生する可能性を減らすため、良い習慣です。初期化されていない変数が不適切な値を与える初期化によって消去されると、特定の静的ツールがうまく機能しなくなり、バグを見つけるのが難しくなると主張する人もいます。ただし、初期化されたデータに基づいている場合、バグはより再現性が高く、バグのある動作はおそらくプラットフォーム間でも移植可能です。一部の言語では、ローカル変数が初期化されます。Lisp では、 (let (x) ...) は、コード ブロック内...で variablexが値NILを持つことを意味します。これは、初期化子がないためです。Lisp コードの静的解析では、次のような事実を簡単に追跡できます。NIL数値関数に不適切に渡されています。intC および関連言語では、 のような型には、 のような間違った型の値に相当するものがないため、問題は少し異なりNILます。これ0は有効な値であり、型の不一致で計算を単純に爆発させることはありません。不適切0であると、計算でアルゴリズムのバグが発生する可能性があります。NILただし、ポインターの場合、null ポインター値は、 「私はどのオブジェクトも指していない」という、プログラマーに見える移植可能なドメイン値であるという点で、 の合理的な複製です。ポインターが実際には当分何も指していない場合、意図しないオブジェクトを誤って指し示す可能性のあるランダムなビットをポインターに残すのではなく、この値を指定する必要があります。

于 2013-01-28T23:03:33.653 に答える