トップ «前の日記(2018-10-10) 最新 次の日記(2018-11-13)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|

2018-10-15 [cocoa][swift]え!それって参照渡し?

とても違和感を感じる用語がある。それは、『参照渡しだ』。

え!違うだろ?と感じていたが、いい機会なので、調べてみた。

引数

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

実引数

関数に渡す値。

sum(1, 2);

仮引数

関数が受け取った変数。

int sum(int a, int b)
{
    return a + b;
}

値渡し(call by value)

値が渡される。

_ <h2>ポインタ渡し

渡す値がアドレスの値渡し。

参照渡し

  • 変数渡し(call by variable)
    変数そのものを渡す。
  • 参照渡し(call by reference)
    参照渡しで、内部でアドレス情報を渡す方法。

Pascal

Pascalでは,値渡し(call by value)と変数渡し(call by variable)が存在し、変数渡しは参照渡しに相当する。

そもそもは、変数渡しの実装方法に参照渡しがある。参照渡しは、変数に対する参照(アドレス情報)を渡す方法だ。

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

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

PROCEDURE GetPort(VAR port: GrafPtr);

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

void GetPort (GrafPtr * port);

C言語

C言語の関数の引数は全て値渡し。K&Rでしっかりと説明されている。

ポインタでアドレスの値を渡すのを参照渡しと呼ぶのは間違いだ。

Java

Javaも全て値渡し。

ポインタ演算ができない、アドレス(参照)の値渡しが利用できるが、これを参照渡しと呼ぶのは、如何なものか。

C++

値渡しに加え、本物の参照渡しが存在する。

void time_two(int& a)
{
    a *= 2;
}

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

C#

二つの参照渡しの方法が用意されている。

int initializeInMethod = 0;  // 初期化が必須
OutArgExample(initializeInMethod);
Console.WriteLine(initializeInMethod);
 
void OutArgExample(ref int number)
{
    number = 44;
}
int initializeInMethod;
OutArgExample(out initializeInMethod);
Console.WriteLine(initializeInMethod);
 
void OutArgExample(out int number)
{
    number = 44;  // 代入が必須
}

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

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

Swift

値渡しだが、inoutキーワードをつけると値呼びの結果返し(call-by-value-result)となる。

C言語のポインターの場合と同様に、変数が参照型の場合、参照の値渡しにより値を変更できる。

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

値呼びの結果返しの例。

func set999(a: inout Int) {
    a =999
}
 
var num = 0
set999(&num)

トップ «前の日記(2018-10-10) 最新 次の日記(2018-11-13)» 編集