2015TweetPocketC言語ではメモリ安全性(プログラムが不正なメモリアクセスを行わないこと)に苦労します。その後の言語ではさまざまなアプローチでメモリ安全性を確保していますが、Swiftでももちろんメモリ安全性を保証しています。blogメモリ安全性:使用時に値が定義されていることを確認Swift言語を設計する上で最も重点をおいたのが、プログラミングモデルでのメモリ安全性を向上することでした。メモリ安全性を測るのに多くの側面がありますが、本記事では単純なケース、値が使用される前に変数が初期化されていることをどうやって確認するか、について解説しています。Swift言語でのアプローチコードが変数にアクセスする前に変数には有効な値が入っているということを開発者が確信できるとき、その変数は「安全」であると言えます。このような安全性を得るために、プログラミング言語はさまざまなアプローチをとります。C言語のように安全なプログラミング技法を採用するのを完全にプログラマの責任とする言語もあります。これは協力なアプローチですが、危険でいっぱいです。C++やObjective-Cではいかつかの必須パターンを強いることによって状況を改善しようとしています。定義時に初期化を強制するといった極端な措置をとる言語もあります。Swift言語で採用された主要な技法は、コードのデータフロー解析を実行するのに私たちの高度なコンパイラを使用することです。コンパイラは変数が使用される前に初期化されているということを強制します。Assignmentとも)として知られる戦略ですが、JavaやC#、その他多くの言語でもこの技法を採用しています。Swift言語では広範囲の変数にこのアプローチの拡張版を使用しています。この記事の最後では他の技法も紹介しています。その多くはSwift言語でも多かれ少なかれ採用しています。ローカル変数の確定初期化Swift言語ではさまざまな場面で確定初期化のルールを適用しますが、ローカル変数への使用がもっとも単純です。確定初期化は「暗黙的初期化」ルールより柔軟性を与えてくれます。以下のコードが許されます。pathsmyInstance.printIt()ここでコンパイラはif式がmyInstanceを初期化することを保証し、初期化されていなメモリへのメソッド呼び出しはできないということを確認します。確定初期化は強力なアプローチですが、信頼でき予測できる場合にだけ本当に便利です。これによって驚かされるのはもっと複雑な制御フローを扱っているときです。{myInstance.printIt()}この例ではコンパイラはprintIt()を呼び出すときに「myInstanceという変数は初期化される前に使用された」ということを教えてくれます。コンパイラはif条件における述語論理式間の関係を追跡しないからです。このような特定のケースについては扱えるようコンパイラに教えることはできますが、すべてのケースにおいては不可能(停止問題のようなもの)です。私たちはコンパイラのルールを単純で予測可能なままにすることを選択しました。Swift言語では変数を初期化するのは極めて簡単です。0と宣言する方が短いです。Swift言語は可能な限り明示的に初期化することを好みます。必要になったときにinit()を使用して変数を初期化するのによりよい方法もいくつかあります。Language(Swift言語仕様)の「初期化」の章を参照してください。他のアプローチSwift言語では確定初期化に加えて、言語仕様上の特定の範囲には別のアプローチも採用しています。他の言語でこの技法を使用しているかもしれませんが、この記事で簡単に触れておきたいと考えています。それぞれはいくつかの欠点がありますので、Swift言語での主要アプローチとしては使用されていません。プログラマに安全性を委ねるC言語の普及を考慮すると、開発者に安全性の向上を委ねることの良し悪しを理解することは大切です。不幸にもC言語において初期化されない値を使用すると予期せぬ動き(未定義な振る舞い)を引き起こし、落ちることがあります。C言語はプログラマが決してミスをしないということを期待しているのです。私たちの目標はSwfit言語を「何もしないでも安全に」することですので、このアプローチは一般的な使用ではすぐに却下されました。UnsafePointerのようなAPIではunsafety(安全でないこと)が絶対に必要なときに限り、明示的にオプトインして使用することができます。暗黙的初期化コンパイラが暗黙的に変数を初期化することによって、変数の安全性を保証できます。Objective−Cでは「ゼロ値」をインスタンス変数にセットしたり、C++ではコンストラクタを実行したりします。このアプローチについても入念に検討しましたが、最終的には広範囲な使用には向かないと結論づけました。このアプローチはinit()が必要ないプロトコルやクラスへのnon-nullableな参照のように、適当な初期値がないときには機能しません。これらはSwift内ではよく使用されています。整数の0のようなプリミティブな型でさえ間違った値であることがあります。これはSwift言語で初期値を設定するのがとても簡単にしている理由の一つですが、コードをメンテナンスする人にとってわかりやすくするのと、省略したことによる潜在的なエラーを避けることです。センチネル(データの終了を示すデータ)に-1が使用されるときがあります。nilを初期値とすることは、nullableの値にとっては正しい解だということには気づいていますか。Optionalやのような型は自動的にnilを初期値として初期化されます。定義時に初期化子を必須にする変数が定義されるときに、常に初期値を与えるのを開発者の責任とします。Intは初期化子として不適切ということになります。これは関数言語ではよく使われるアプローチですが、かなり厳密なプログラミングスタイルを強いるためにこの要求は重すぎる、自然なパターンを表現するのに邪魔になると考えました。