Swift5 引数の参照渡し


引数でよくつまづくので、分かった事をまとめてみました。完全に初心者向けの記事です。

引数の性質

関数を記述する時、計算する値を関数外から入れたい時に使用するものが引数ですが、引数は値渡です。

よって、引数として値を渡したら、当然変更はできません。
下の例で実験します。

var taxCon :Int = 0
var taxLoc :Int = 0
var value :Int = 108

func taxAddValue(price:Int, sorting:String){
    if sorting == "軽減税率"{
        taxCon = (price / 108 * 624 + 50) / 100
        taxLoc = (price / 108 * 176 + 50) / 100
        print(taxCon)
        print(taxLoc)
    }else if sorting == "経過措置税率" {
        taxCon = (price / 108 * 630 + 50) / 100
        taxLoc = (price / 108 * 170 + 50) / 100
    } else {
        taxCon = (price / 110 * 780 + 50) / 100
        taxLoc = (price / 110 * 220 + 50) / 100
    }
}

taxAddValue(price: value, sorting: "軽減税率")

上記の関数は、消費税及び地方消費税を消費税と地方消費税に分解するものです。
ここで、金額である変数valueは引数として関数に引き渡されます。
値渡しでなければ、関数内で変更する事ができるはずですが・・・

試しに、引数のpriceの金額を変更しようとしてみます。

例 priceを変更
var taxCon :Int = 0
var taxLoc :Int = 0
var value :Int = 108

func taxAddValue(price:Int, sorting:String){
    price = 216 //ここでエラーが出る

エラーが出て、priceの前にletを置いて変数として定義するよう求められます。
つまり、引数priceと別の変数priceとして使うように指摘されます。

これによって、引数は値のコピーであり、引数を渡した後で変更する事ができない事がわかります。

それによってどうなる?

値型の場合、インスタンス化する際は値のコピーとなるので、そのコピーを引数として値渡しする為、プロパティを変えることができません。

参照型(クラス)の場合、引数にとった時、当然参照先のコピーなので、引数として渡すまでに必要な設定していなければイニシャライズされていないものを渡す事と同じと言うことになります。

じゃあどうする?

inout引数を使えば、解消できます。
この引数は引数の性質を値渡しから参照渡しにできます。

上記の例を用いてまた実験します。

例 inout引数を使う
var taxCon :Int = 0
var taxLoc :Int = 0
var value :Int = 108

func taxAddValue(price:inout Int, sorting:String){
    price = 216
    if sorting == "軽減税率"{
        taxCon = (price / 108 * 624 + 50) / 100
        taxLoc = (price / 108 * 176 + 50) / 100
        print(taxCon)
        print(taxLoc)
    }else if sorting == "経過措置税率" {
        taxCon = (price / 108 * 630 + 50) / 100
        taxLoc = (price / 108 * 170 + 50) / 100
    } else {
        taxCon = (price / 110 * 780 + 50) / 100
        taxLoc = (price / 110 * 220 + 50) / 100
    }
}


taxAddValue(price: &value, sorting: "軽減税率")

無事、エラーが出ずに引数を書き換えられました。

変えたところは2点です。
関数の設定時の変数名と型名の間にinoutを記述
呼出しの方で、変数名と型名の間に&を記述しました.

これによって、引数を参照渡しにする事ができます。

参照渡し

参照渡しとは、その変数のアドレスを引き渡す事です。
アドレスは変数が格納されている場所を指し、C言語ではポインタなどと呼ばれています。
これは値ではなくアドレス値を引き渡すので、変数そのものの値を書き換える事ができます。
ただし、書き換えるので元の値は失われます。

最後に

このあたりの事は基礎に当たる部分ですが、とても分かりにくい部分です。
同じような沼にハマっている人の助けになれれば幸いです。
何か間違っている事があれば、教えてください。