引数とは
プログラミングにおいて、関数や手続きが外部から値を受け取るための仕組みが
引数です。引数には、関数を定義する際に使われる
仮引数と、関数を呼び出す際に実際に渡される
実引数の2種類があります。
仮引数
仮引数は、関数の定義時に指定される変数であり、関数が呼び出されたときに、実引数の値を受け取るための入れ物のようなものです。例えば、
C言語の例では、以下のように関数`sum`を定義したとき、`addend1`と`addend2`が仮引数です。
c
int sum(int addend1, int addend2) {
return addend1 + addend2;
}
関数内では、この仮引数を使って処理を行います。
実引数
実引数は、関数を呼び出す際に、仮引数に対応する値として実際に渡される値のことです。上記の`sum`関数を呼び出す例では、以下のように`123`と`456`が実引数となります。
c
int result = sum(123, 456);
この場合、`123`が`addend1`に、`456`が`addend2`に渡され、関数内で計算が行われます。
引数の渡し方
引数の渡し方には、いくつかの種類があり、言語によって採用されている方法が異なります。
値渡し
値渡しは、実引数の値をコピーして仮引数に渡す方法です。関数内で仮引数の値を変更しても、元の実引数の値には影響しません。
C言語、
Java、MLなどが値渡しを採用しています。この方式は関数が副作用を持たないため、計算を中心とする言語では望ましい動作とされます。
ポインタ渡し
ポインタ渡しは、実引数の
メモリアドレスを値として渡す方法です。
C言語や
C++のポインタは
メモリアドレスを保持するため、ポインタを値渡しすることで、参照渡しのような効果を得ることができます。ただし、これは値渡しの一種であり、参照渡しとは異なります。
名前渡し
名前渡しは、実引数として渡された式を、その都度評価して値を計算する特殊な方法です。
ALGOLで採用されていましたが、複雑な動作のため、他の言語ではほとんど採用されていません。実引数に変数だけでなく式も渡せるという特徴があります。
変数渡し
変数渡しは、変数そのもの(左辺値)を渡す方法で、仮引数に対する操作が実引数に直接影響を与えます。参照渡しは変数渡しの一種です。変数渡しを行う場合、配列などのデータ構造を効率的に変更できます。
Pascal、
Perl、
C++、C#などが変数渡しをサポートしています。
参照渡し
参照渡しは、実引数の参照(
メモリアドレス)を渡す方法です。関数内で仮引数を通して値を変更すると、元の実引数の値も変更されます。
C++やC#などでサポートされています。参照渡しは、変数渡しの実装手段の一つと見なすこともできます。
参照の値渡し
参照渡しでいうところの「参照」と、言語で「参照」と呼ばれているものが必ずしも同じではないことに注意が必要です。例えば、
Javaの参照はポインタに近い概念で、参照渡しとは異なる場合があります。
値渡しによる変数の変更
C言語は値渡しのみをサポートしますが、ポインタを渡すことで元の変数を変更できます。しかし、これはあくまで値渡しによる参照のエミュレーションであり、言語の保護下にある参照とは異なります。
遅延評価は、値が必要になるまで計算を行わない方法です。
Haskellなどの関数型言語で使われ、効率的なプログラム実行に役立ちます。計算方法を遅延したthunkオブジェクトが渡されるという考え方です。
まとめ
引数の渡し方は、
プログラミング言語によって異なり、それぞれの特徴を理解することで、より効率的で安全なプログラムを作成することができます。値渡し、参照渡し、ポインタ渡しなど、それぞれの仕組みと注意点を理解し、適切に使い分けることが重要です。また、言語によっては、引数の渡し方によって予期せぬ動作を引き起こす可能性があるため、注意が必要です。