##値渡しってなんぞ
関数を呼ぶとき、引数って使いますよね。
このとき、呼び出した先に渡された値は、呼び出し元の変数をコピーして使っています。
つまり、呼び出し先の関数でこの引数を変更しても、呼び出し元にはまったく影響がないということです。
public function start()
{
$number = 10;
// 上記の変数を使って関数を呼びます
$this->oneUp($number);
echo '3:' , $number, ' 関数の後、呼び出し元の値', PHP_EOL;
}
private function oneUp(int $number)
{
echo '1:', $number, ' これが関数に渡された値', PHP_EOL;
$number += 1;
echo '2:', $number, ' 引数に1を足した値', PHP_EOL;
}
実行結果
1:10 これが関数に渡された値
2:11 引数に1を足した値
3:10 関数の後、呼び出し元の値
「3:」の値が変化していないことから、コピーであることがわかります。
これを値渡しと言います。
##値渡しで進める通常の処理
せっかく関数で増やしたんだから呼び出し元でも使いたいよ、というとき、
人は呼び出し元で「別の変数」として受け取ります。
public function start()
{
$number = 10;
// 左辺で別変数を指定する
$oneUpNumber = $this->oneUp($number);
echo '3:' , $oneUpNumber, ' 関数の後、呼び出し元で受け取った値', PHP_EOL;
}
private function oneUp(int $number)
{
echo '1:', $number, ' これが関数に渡された値', PHP_EOL;
$number += 1;
echo '2:', $number, ' 引数に1を足した値', PHP_EOL;
// 呼び出し先でもreturnで値を返す
return $number;
}
実行結果
1:10 これが関数に渡された値
2:11 引数に1を足した値
3:11 関数の後、呼び出し元で受け取った値
こんな感じで、通常は処理を進めます。
##参照渡し
ところが、こういった手順を踏まなくても、
呼び出し先で、呼び出し元の値を書き換えてしまう渡し方があります。
それが参照渡しです。
public function start()
{
$number = 10;
// 上記の変数を使って関数を呼びます
$this->oneUp($number);
echo '3:' , $number, ' 関数の後、呼び出し元の値', PHP_EOL;
}
// 受け取った引数の頭に&をつける
private function oneUp(int &$number)
{
echo '1:', $number, ' これが関数に渡された値', PHP_EOL;
$number += 1;
echo '2:', $number, ' 引数に1を足した値', PHP_EOL;
}
実行結果
1:10 これが関数に渡された値
2:11 引数に1を足した値
3:11 関数の後、呼び出し元の値
関数で受け取った引数の頭に「&」をつけたことで「3:」の値が変化しました。
呼び出し先の関数でも呼び出し元の変数(メモリアドレス)を「参照」しているからです。
##ここが大事な注意点
ところが、ソースの中でこういった参照渡しが存在すると、
「あれ、変数の値が途中でいつの間にか変わってる???」
という混乱の元になります。
同じ名前の変数が処理の前後で値が変わっていてしまうと、
そのことに大変気付きにくいので、大災害の火種になりかねません。
関数で値を変えて、それを使いたいのであれば別の変数として受け取りましょう。
ちなみにPHPではオブジェクトはデフォルトで参照渡しです。これも注意しましょう。
追記
デフォルトで参照渡しというのは間違いです。こちらの記事参照。
同じ方の&(リファレンス)の使い方の記事も参考になりました。