PHPにおける値渡しと参照渡し

PHP 5.4で調査や検証を行って分かったことがあったのでまとめておく。

Javaなどの言語では,プリミティブ型の変数への代入では「値渡し」が行われ,参照型の変数への代入では「参照渡し」が行われているがPHPでもそうなのかを検証してみる。

値渡し

プリミティブ型を変数に代入するときは値渡しが行われるので$b$aを代入した後で$aに対して操作を行っても$bには影響を与えないということが以下のコードから理解出来る。

$a = 1;
$b = $a;
$a = $a + 1;

//1 を出力する
echo $b;

参照渡し

参照型を変数に代入するときは参照渡しが行われるので$b$aを代入した後で$aに対して操作を行うと$bに影響を与えるということが以下のコードから理解出来る。

$a = new DateTime('2000-01-01');
$b = $a;

//1日加算 2000-01-02
$a->add(new DateInterval('P1D'));

//2000-01-02 を出力する
echo $b->format('Y-m-d');

値の参照渡し

プリミティブ型を変数に代入するときは通常の場合は値渡しが行われるが&を使うことで参照渡しを行うことが出来る。これにより$b$aを代入した後で$aに対して操作を行うと$bに影響を与えるということが以下のコードから理解出来る。

$a = 1;
$b = &$a;
$a = $a + 1;

//2 を出力する
echo $b;

メソッドへの値の参照渡し

メソッドへ値の参照渡しを行う方法も用意されているが,仕様が煩雑なため,個人的にはあまり使いたくない代物である。なので,ここでは紹介までに留める。

どうしても使用したい場合はPHPマニュアルの以下の記事を参考にする。

PHP: リファレンス渡し – Manual
PHP: リファレンスを返す – Manual

※メソッドに参照を渡すだけではreturnする際にコピーが発生してしまうので、参照を返すところまで意識してコーディングする必要がある点に注意。

参照の値渡し

参照型を変数に代入するときは通常の場合は参照渡しが行われるがcloneを使うことで値渡しを行うことが出来る。これにより$b$aを代入した後で$aに対して操作を行っても$bには影響を与えないということが以下のコードから理解出来る。

$a = new DateTime('2000-01-01');
$b = clone $a;

//1日加算 2000-01-02
$a->add(new DateInterval('P1D'));

//2000-01-01 が出力される
echo $b->format('Y-m-d');

単純に参照型を変数に代入するだけでは変数がお互いに影響を与えあってしまい,使い勝手が良くないのでPHPにはcloneという参照型のコピーを作成する機能が用意されている。

まとめ

変数に何かを代入するときは,以下の4つのことを意識する。

  • 値渡し(値の値渡し)
  • 参照渡し(参照の参照渡し)
  • 値の参照渡し
  • 参照の値渡し

参考
PHP: リファレンス渡し – Manual
PHP: リファレンスを返す – Manual
オブジェクト変数の値渡し – PHPリファレンス
PHPが糞言語なのはどう考えても参照をポインタだと思っているお前らが悪い – なんたらノート第三期ベータ
PHP 参照について 3