引数
出典: フリー百科事典『ウィキペディア(Wikipedia)』
引数(ひきすう、argument=実引数 または parameter=仮引数)とは、プログラミング言語において関数やメソッドを呼び出すときに、その関数やメソッドを実行するために渡す値のこと。
次のC言語系言語における文では、「func
」が関数名もしくはメソッド名、「args
」が(仮)引数、「int
」が(仮)引数の型になる。
func(int args);
目次 |
[編集] 値渡し
値渡しは新たに値のコピーを作って渡す方法で、元の内容と同じだが独立した新たな変数が関数内に用意される。そのため外から何らかの変数を渡したとしても、実際に渡るのは変数の値のみであり、元々の変数が変更される事は起こらない。
これは「関数が副作用を持たない」という観点から、計算を中心とする言語では望ましい動作といえる。またそもそも代入概念の存在しない関数型言語では、引数は必ず値で渡されると考えられる(ただし、代入が存在しない以上コピーをとる必要もない)。
値渡しを採用した言語としてはC、Java言語、ML、APL、Scheme等が挙げられる。
[編集] 参照渡し
参照渡しは変数そのものに対する参照を渡す方法で、この場合は引数に対する操作がそのまま渡された変数に影響する。オブジェクトに対する副作用でプログラムを構成するオブジェクト指向言語では参照渡しを用いる事が多い。Cが値渡しの言語であるのに対して、C++が参照渡しをサポートするのもこの理由による。
また参照渡しをサポートする言語でも、即値は実質的に値渡しで行われる。
原始的な言語であるFORTRANは機械語のアドレス操作を反映した参照渡ししか持たなかった。他に参照渡しをサポートする言語としては、Pascal、Perl、C++、C#などが挙げられる。
[編集] 値渡しと参照渡しの関係
C言語は原則として値渡しのみをサポートするが、ポインタによって変数への参照値(メモリアドレス)をとり出せるため、参照値を渡して元の変数を変更できる。特に初期のCは浮動小数点数を除けば、全ての値はint互換であると考えられており、オフセット計算により構造体の一部分を参照するコードも容易に記述できる。
しかしこれは、実際の変数領域を逸脱した部分をも参照できるので、あくまでも値渡しによる参照渡しのエミュレートである。参照渡しをサポートする言語でも内部的には同様の操作を行っているが、それは何らかの意味で言語の保護下にある参照となる。
- 例:Pascalの参照渡し
- Pascalの手続き(procedure)や関数(function)では、原始型(integer, realなど) の値渡しと参照渡しのどちらでも行える。参照渡しの場合は手続き・関数の引数にvarを付ける。
{ 手続き swap 内で a,b の値を入れ替える。 sampleの i,j は参照渡しされ、aとi、bとjは同じアドレスを指して いるので、i,jの値は入れ替わる。 } procedure swap(var a,b:integer); { var をつけると参照渡し } var tmp:integer; begin tmp := a; a := b; b := tmp end; procedure sample(); var i, j:integer; begin i := 5; j := 10; swap(i, j); ... { iは10, jは5になる } end;
[編集] 遅延評価
Haskellなどの遅延評価型関数言語に見られる形態で、値が実際に必要になるまで計算を行わない方法。概念上は、計算方法を遅延したthunkと呼ばれるオブジェクトが渡っていると考えられる。
[編集] 名前渡し
ALGOLで採用されていた特徴的な機能の一つである。名前渡しでは値でも参照でもなく、式がそのまま渡される。基本的には参照渡しのように振る舞うが、式を参照するごとに値を計算して取り出す事が特徴である。次のような例は名前渡しに特徴的な動作と言われる。
swap(x,y) { tmp = x; x = y; y = tmp; }
この例に対し、x=i, y=a[i]
という"式"を渡すとする。仮にi=2だったとすると、
tmp = x;
- x=i=2 なのでtmpは2になる
x = y;
- xはiを渡されているのでiがyの値になる。yはa[i]だから、iはaの2番目の値になる
y = tmp;
- yはaのi番目の値だが、前手順によりiはa[2]になっている。従ってy=a[a[2]]になる。
このような複雑さもあって、ALGOL以外で名前渡しが採用された事例はほとんどない。