Swiftのinoutキーワードは、関数が渡されたパラメータの値を直接(参照によって)変更できるようにします。これは、他のいくつかの言語での参照渡し(pass-by-reference)に相当します。
例:
func increment(_ value: inout Int) { value += 1 } var x = 10 increment(&x) // これで x == 11
varで宣言された変数のみに適用され、letを渡すことはできません。質問: 構造体のプロパティをinoutパラメータを持つ関数に渡すことはできますか?その構造体は他のオブジェクトの一部として使用されていますか?
回答: いいえ、Swiftは同じプロパティへの同時アクセスを一つの命令内で禁止しているため、レースコンディションや不確定な動作を回避します。例:
struct Point { var x: Int var y: Int } var p = Point(x: 1, y: 2) increment(&p.x) // ok increment(&p.y) // ok // increment(&p.x, &p.x) // コンパイルエラーを引き起こします
体験談
あるプロジェクトで、開発者は同じ変数を同時に二つのinout修飾子を持つ関数パラメータに渡そうとしたため、コンパイルエラーが発生しました。これにより、関数のアーキテクチャを見直し、変更を二段階に分けることになりました。
体験談
実装者はinoutパラメータを通してループ内で配列を変更していたが、その結果は予想外のものでした。Swiftは渡すときに内容をコピーするため、変更がループ間で同期されませんでした。
体験談
開発者はinoutパラメータが常に「参照渡し」で動作すると期待していましたが、クラスや構造体と作業する際にcopy-in/copy-outのセマンティクスに遭遇し、構造体のネストされたオブジェクトが変更された場合にすべての変更が保持されないことに気付きました。