2016/10/18 20:41:29

PHPの参照はCのポインタとは別物

php-logo
目次(クリックするとジャンプします)
  • 1:PHPの参照とはいったい…
  • 2:じゃあなんのメリットあるの?
  • 3:まとめ

PHPの参照とはいったい…

PHPでは参照のことをリファレンス(訳したら参照ですが)と呼んでいます。

この参照というのはCで言うところのポインタのことだと思っていました。ところが全然違いました…。

Cのポインタはメモリアドレスが格納されるかと思いますが、PHPのリファレンスではメモリアドレスが格納される訳ではなく、だからポインタの演算ができるわけでもないとのこと。

UNIX系のハードリンクとファイル本体の関係と同じようなものだと説明されています。なるほど。

PHP において、リファレンスとは同じ変数の内容を異なった名前で コールすることを意味します。これはCのポインタとは異なります。 リファレンスを使ってポインタの演算をすることはできませんし、 リファレンスは実メモリのアドレスでもありません。詳細は リファレンスが行わないこと を参照ください。 そうではなく、リファレンスはシンボルテーブルのエイリアスです。 PHP では、変数名と変数の内容は異なっており、 このため、同じ内容は異なった複数の名前を有する事が可能であることに 注意してください。最も良く似ているのは、Unix のファイル名とファイルの 関係です。この場合、変数名はディレクトリエントリ、変数の内容は ファイル自体に対応します。リファレンスは、Unix ファイルシステムの ハードリンクのようなものであると考えられます。

PHPマニュアル リファレンスとは? http://php.net/manual/ja/language.references.whatare.php

つまりただの別名、エイリアスということのようですよ。ポインタのようにアドレスを指しているのではなく、まんま変数の内容を指しているだけのようです。

異なる変数名で値を共有しているような感じですから、リファレンスに対しての処理は変数の値にダイレクトに影響を与えます。場合によっては予期せず値を壊しかねないので意外と危険なのかもしれません。

リファレンスを扱うには&演算子を用います。

例えばこんな感じで書くと、

$a = & $b;

変数$aと変数$bは同じ内容を指します。ポインタのように$b$aのアドレスが入るとかそういう訳ではありません。単に$b$aの別名、$a$bの別名になったというだけです。

<?php

$a = &$b;
$b = $b + 10;
var_dump($a);
var_dump($b);

これは

(int)10
(int)10

となります。$aをつかって処理はしていませんが、$a$bは同じ値を格納する変数の別名同士の関係となったので、どちらも値10を表示します。

リファレンスを返すことは、結合する変数を見付けるために関数を使用し たい場合に便利です。パフォーマンスを向上させるためだけの目的で この機能を用いることはやめてください。 そのようなことをしなくても、PHP エンジンが自動的に最適化を行います。 リファレンスを返すのは、そうすべき妥当な理由がある場合に限られます!

PHPマニュアル リファレンスを返す http://php.net/manual/ja/language.references.return.php

「ポインタのような効果を期待するな」と書かれていますね。パフォーマンス向上のために使うものでは無いと。

どうもいろいろ情報を漁ると、PHPの参照は他の言語の参照と趣が異なるようです。なので他の言語のポインタ、参照の概念をそのまま当てはめて考えるのは危険かもしれません。

じゃあなんのメリットあるの?

マニュアル読んでもみてもはっきり「これがメリットです」というポイントがわからなかったです…。

いったいリファレンスの使いドコロっていったいどこなんだろう?

スコープを超えた、たとえば関数の内部から外部の変数をイジるとかのために使うんだろうか?

まとめ

  • PHPの参照(リファレンス)はポインタのことではない
  • PHPの参照(リファレンス)は変数の別名を設定するような機能(C++の参照に似ている?)
  • なので値を共有することになり、不用意に値を変更してしまうことになりかねない
  • あまりメリットがわからなかった
  • わからないうちは使わないでおこう