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

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

プリミティブ型と参照型

PHPの変数の型には,大きく分けて「プリミティブ型」と「参照型」の2つが存在する。ここでは説明を省きたいので,それぞれの違いについては,この記事をご閲覧いただきたい。
 

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

上記の説明から,プリミティブ型の変数への代入では「値渡し」が行われ,参照型の変数への代入では「参照渡し」が行われていることが理解出来る。
 
PHPのコードを書いて実験してみる。

$a = 1;
$b = $a;
$a = $a + 1;
echo $b; //1 を出力する

 
プリミティブ型を変数に代入するときは,値渡しが行われるので,$bに$aを代入した後で,$aに対して操作を行っても$bには影響を与えない。
 

$a = new DateTime('2000-01-01');
$b = $a;
$a->add(new DateInterval('P1D')); //1日加算 2000-01-02
echo $b->format('Y-m-d');         //2000-01-02 を出力する

 
参照型を変数に代入するときは,参照渡しが行われるので,$bに$aを代入した後で,$aに対して操作を行うと$bに影響を与える。
 

僕の知ってる参照渡しと違うんだけど…

あなたの知っている参照渡しは,おそらく以下のようなコードではないだろうか。

$a = 1;
$b = &$a;
$a = $a + 1;
echo $b; //2 を出力する

 
プリミティブ型を変数に代入するときは,通常の場合は値渡しが行われるが,&を使うことで参照渡しを行うことが出来るので,$bに$aを代入した後で,$aに対して操作を行うと$bに影響を与える。
 
あまり聞かないが,これは「値の参照渡し」とでも呼べば覚えやすい気がする。
 
※ちなみにメソッドに対して,値の参照渡しを行うときは,「参照返し」も一緒に行わないと, return されたときに値のコピーが発生してしまうので注意が必要である。
 

参照型のコピーを作成する方法

では,PHPで参照型のコピーを作成するにはどうすれば良いのか。上記で示した参照型の代入の例のように,単純に参照型を変数に代入するだけでは,変数がお互いに影響を与えあってしまうので,これでは使い勝手がよくない。
 
そこで,PHPにはcloneという命令が用意されており,これを使うことで参照型が格納された変数のコピーを作成することが出来る。
 

<?php
$a = new DateTime('2000-01-01');
$b = clone $a;
$a->add(new DateInterval('P1D')); //1日加算 2000-01-02
echo $b->format('Y-m-d');         //2000-01-01 が出力される

 
参照型を変数に代入するときは,通常の場合は参照渡しが行われるが,cloneを使うことで値渡しを行うことが出来るので,$bに$aを代入した後で,$aに対して操作を行っても$bには影響を与えない。
 
これは「参照の値渡し」と呼ばれる。
 

まとめ

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

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

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

Article written by

コメントを残す