2024/01/10 12:31
Copy-In Copy-Out は、関数またはメソッドに引数を渡す方法のひとつです。
この方法を用いた場合、引数として渡された値は、それがコピーされたものが関数内に渡され、関数の処理を終えて戻るときに、関数内にコピーされていた値が呼び出し元の値としてコピーされます。このような仕組みから Write Back
と呼ばれることもあるようです。
定義
Swift では inout
キーワードを用いて、引数が Copy-In Copy-Out
渡しであることを指定できます。
func increment(value: inout Int, step: Int) {
value += step
}
使用
値を Copy-In Copy-Out
に指定された引数に渡したいときには、var
で宣言した変数に値を入れる必要があり、定数 let
やリテラルを指定することはできません。また、変数を渡す場合も、それが inout
引数に対して渡している意図が明確になるように、変数名の前に &
を添えて渡す必要があります。
この記号は、他の言語に見られるような「参照渡し」を意味するものではなく Copy-In Copy-Out
渡しを意味する記号になります。ただ、Swift では下記のように最適化が図られ、実質的に参照渡しとして機能することが多くあります。
最適化
Copy-In Copy-Out
渡しは、渡すものがメモリーを直接操作する変数である場合には「参照渡し」で値を渡すように最適化されます。これにより、値の書き換えが直接的に元の変数に対して行われるため、関数に入る時と出る時に値が複製されるコストを省くことができます。ただし、本来の動作である「関数を抜ける際に元の値を書き変える」のではなく「関数内で値を書き換えた時点で元の値も書き変わる」ため、最適化により値の書き換えタイミングが大きく変わってくることになります。
この、最適化の有無による動作の違いでバグを生まないために、Swift では「inout
引数に渡した変数は、渡した関数の実行が終わるまで参照してはならない」と、Apple 公式の に記されています。