[cocoa][swift]え！それって参照渡し？

# はじめに
<p>とても違和感を感じる用語がある。それは、『参照渡しだ』。<br />
え！違うだろ？と感じていたが、いい機会なので、調べてみた。</p>

# 引数
<p>引数と呼ばれるものにどんな種類があるのか、まずは列挙してみる。</p>

## 実引数
<p>関数に渡す値。</p>

<pre><code>sum(1, 2);
</code></pre>

## 仮引数
<p>関数が受け取った変数。</p>

<pre><code>int sum(int a, int b) {     return a + b; }
</code></pre>

## 値渡し(call by value
<p>値が渡される。</p>

## ポインタ渡し
<p>渡す値がアドレスの値渡し。</p>

## 参照渡し

### 変数渡し(call by variable)
<p>変数そのものを渡す。</p>

### 参照渡し(call by reference)
<p>参照渡しで、内部でアドレス情報を渡す方法。</p>

<p>自分の理解では、初期のプログラミング言語ではローカル変数の実装が困難で、変数はグルーバル。なので、変数渡し。近年の高級言語でローカル変数が実現され、その流れで値渡しが用意されたのかなと思っている。</p>

# Pascal
<p>Pascalでは，値渡し(call by value)と変数渡し(call by variable)が存在し、変数渡しは参照渡しに相当する。</p>

<p>そもそもは、変数渡しの実装方法に参照渡しがある。参照渡しは、変数に対する参照（アドレス情報）を渡す方法だ。</p>

<p>Inside Macintoshは、コードはPascalで記載されているが、それをC言語で利用する場合、varがついた変数渡しの引数は、C言語ではポインターと読み替えていた。</p>

<p>具体的には、Inside Macintoshで以下のようにPascalで説明されていたとする。</p>

<pre><code>PROCEDURE GetPort(VAR port: GrafPtr);
</code></pre>

<p>これをC言語では、以下のように読み替える。</p>

<pre><code>void GetPort (GrafPtr *port);
</code></pre>

# C言語
<p>C言語の関数の引数は全て値渡し。K&Rでしっかりと説明されている。<br />
ポインタでアドレスの値を渡すのを参照渡しと呼ぶのは間違いだ。</p>

# Java
<p>Javaも全て値渡し。<br />
ポインタ演算ができない、アドレス（参照）の値渡しが利用できるが、これを参照渡しと呼ぶのは、如何なものか。</p>

<p>0'RellyのJavaクイックリファレンスでは、Javaは配列とオブジェクトを参照を通じで扱うと説明されていた。また、参照渡しという言葉と混同しないようにと書かれていた。<br />
参照型の値渡しが参照渡しと勘違いされるのは、仮引数の参照型の中身の値の変更が、実引数側に反映されるからだと思うが、参照先自体の変更ができない。これは、C言語で、引数で渡されたポインターが指す先の値は変えらるがアドレスは変えられない。変えたい場合は、ポインターのポインタを利用するしかないということから分かると思う。</p>

<pre><code>
static char a[] = "hello";
static char b[] = "world";
 
void set_b(char **handle)
{
    *handle = b;
}
 
in t main(int argc, char *argv[])
{
    char *ptr = a;
    printf("%s\n", ptr);
    set_b(&ptr);
    printf("%s\n", ptr);
    return EXIT_SUCCESS;
}
</code></pre>

# C++
<p>値渡しに加え、本物の参照渡しが存在する。</p>

<pre><code>void time_two(int& a)
{
    a *= 2;
}
</code></pre>

<p>また、C++11では右辺値参照・ムーブセマンティクスという所有者の移動が用意されている。</p>

# C#
<p>二つの参照渡しの方法が用意されている。</p>

## ref
<pre><code>int initializeInMethod = 0;  // 初期化が必須
OutArgExample(initializeInMethod);
Console.WriteLine(initializeInMethod);
 
void OutArgExample(ref int number)
{
    number = 44;
}
</code></pre>

## out
<pre><code>int initializeInMethod;
OutArgExample(out initializeInMethod);
Console.WriteLine(initializeInMethod);
 
void OutArgExample(out int number)
{
    number = 44;  // 代入が必須
}
</code></pre>

<p>refは変数が渡されるので、初期化によって値が設定されていない変数はNGだ。</p>

<p>outは値を返すという意味から、初期化は必須でないか、関数内で値を必ず設定しないといけない。</p>

# Swift
<p>値渡しだが、inoutキーワードをつけると値呼びの結果返し（call-by-value-result）となる。<br />
C言語のポインターの場合と同様に、変数が参照型の場合、参照の値渡しにより値を変更できる。</p>

<pre><code>class Demo {
    public var num = 0;
}
 
func set999(a: Demo) {
    a.num = 999;
}
 
let demo = Demo()
set999(demo)
</code></pre>

<p>値呼びの結果返しの例。</p>

<pre><code>func set999(a: inout Int) {
    a =999
}
 
var num = 0
set999(&num)
</code></pre>

<p>少し複雑に感じるが、基本、C言語と同様と考えると成る程だ。</p>

【関連情報】
<a href="https://qiita.com/advent-calendar/2018/cocoa">Cocoa Advent Calendar 2018</a><br />
<a href="https://cocoa-kanto.connpass.com/event/111294/">Cocoa.swift 2019-01</a><br />
<a href="https://cocoa-kanto.connpass.com/">Cocoa.swift</a><br />
<a href="https://www.facebook.com/groups/cocoa.kanto/">Cocoa勉強会 関東</a><br />
<a href="http://www.bitz.co.jp/weblog/">Cocoa練習帳</a><br />
<a href="https://qiita.com/m_yukio">Qiita</a><br />