Swift 5.5の登場により、オーナーシップモデルとムーブセマンティクスの概念が言語に統合され、データの所有権に対する制御が強化され、コンパイラが移動を最適化し、コピーの数を減らすことが可能になりました。これは高パフォーマンスなシナリオにおいて重要です。
ムーブセマンティクスは、値(例えば、構造体)を渡す際に、その値の所有権をコピーなしで「渡す」ことができることを意味します。この時、コンパイラは元の変数を無効にすることができます(C++のムーブに類似)。現在、オーナーシップモデルとムーブセマンティクスは実験的に実装されており(アクターの隔離、送信可能な型、@_move、消費型/自己消費型)、今後公開APIに登場する予定です。
ARCとの主な違いは、ムーブセマンティクスが値型に適用されるのに対し、ARCは参照型オブジェクトのライフサイクルを管理することです。
例(所有権セマンティクス、Swift 5.5+):
func consume<T>(_ x: __owned T) { /* ... */ } struct LargeArray { var storage: [Int] mutating func clear() { storage.removeAll() } consuming func consumeSelf() { // selfは呼び出し後に利用できない } }
所有権管理により、大きな構造体を扱う際の予期しないコピーを避けることができます。
注意点:
Swiftにおける構造体のオブジェクトを値渡し、参照渡し、ムーブセマンティクスで関数に渡すことの違いは何か?
回答:
例:
func foo(_ x: MyStruct) { /* コピー */ } func bar(_ x: inout MyStruct) { /* 参照渡し */ } func baz(_ x: __owned MyStruct) { /* ムーブセマンティクス、コピーしない */ }
物語
プロジェクトでは、大きな構造体を関数を介して渡す際に常に不明なコピーが発生し、メモリコストが増加していました。実験的ムーブセマンティクスの導入と、より洗練された所有権管理により、負荷をクリーンに再分配し、クリティカルな部分のパフォーマンスを向上させることができました。
物語
多くの開発者は、inoutを誤って使用し、ムーブを実現できると考えていましたが、値は引き続き利用可能であり、変数の所有権が不明確になり、バグやロジックの破綻を引き起こしました。
物語
スレッド間のデータ管理エラー:構造体にSendable修飾子が欠如しており、大きな構造体をアクターやタスクを介して非同期に扱う際に予期しないコピーや所有権のエラーが発生していました。