web-dev-qa-db-ja.com

PHPでリファレンスがほとんど使用されないのはなぜですか?

私はC++の知識があり、そこでポインタが一般的に使用されることを知っていますが、PHPオープンソースコードを調べ始めており、メソッド内で参照を使用するコードを決して見ません。

代わりに、変数への参照をメソッドに渡すのではなく、コードは常に戻り値を使用します。これにより、変数の値が変更されて返されます。

リファレンスを使用するとメモリ使用量が少なくなることを読んだので、なぜPHPで使用しないのですか?

26

参照がほとんど使用されないというあなたの主張は正しくありません。他の人がすでに言及したように、参照を使用するネイティブ関数がたくさんあるので、注目すべき例には 配列ソート関数preg_match()/preg_match_all()があります。コードでこれらの関数のいずれかを使用している場合は、参照も使用しています。

次に進むPHPはではないポインタです。C++のバックグラウンドから来ているので、混乱、しかしPHP参照は完全に異なる獣であり、それらは シンボルテーブル のエイリアスです。C++参照から期待されるパフォーマンスの向上は適用されません。 PHPを参照。

実際、ほとんどのシナリオでは、値による受け渡しは、参照による受け渡しよりも高速でメモリ使用量も少なくなります。 PHPのコアであるZend Engineは、変数が変更されるまで変数のコピーを作成しない copy-on-write 最適化メカニズムを使用します。参照渡しは通常、コピーオンライトパターンを壊し、値を変更するかどうかに関係なくコピーが必要になります。

必要に応じてPHPで参照を使用することを恐れないでください。ただし、マイクロ最適化を試みるためだけに使用しないでください。覚えておいてください 時期尚早な最適化がルートですすべての悪の

参考文献:

49
yannis

PHPは、何かを変更するまで新しい値を作成しないコピーオンライトの処理をすでに実行しているため、参照を使用することで節約されるメモリは多くありません。そうすることで、いくつかのことを混乱させることもできますPHP=内部的にメモリ使用量を減らし、事態をさらに悪化させます。

それに加えて、参照は一般的に物事を少し不思議にします。デフォルト、つまりほとんどの人が期待するのは、値渡しです。 $iを関数に渡すと、その関数が$iを完全に別の何かに不思議な形で変更するかどうかを気にする必要が非常に複雑になり、万が一に備えて防御的なコピーを作成します。 (値がオブジェクトの場合は、すでに$iを変更できますが、私の意見ではそうではありません。)

基本的に、参照渡しは「出力」パラメーターにのみ役立ちます。つまり、変数に渡すのではなく、関数からget backを期待している変数を意味します。lapreg_match 's &$matchessortarray_popのように、渡されたオブジェクトを明確に変更する関数についても、少し不快に感じます...しかし、それは私たちが行き詰まっているものです。

8
cHao

PHPはWeb指向の言語です。
Webページは高速で提供され、軽量である必要があります。
通常PHPプログラムは、ほんの一瞬で動作し、数百キロバイトのメモリを消費します。
そのような最適化は役に立ちません。

5

その場でのいくつかの理由:

  • PHPはスクリプト言語であり、コア組み込みソフトウェアとしての使用を目的としていません(基本的に、スクリプトの最後でメモリがクリアされます)。
  • PHP5以降、オブジェクトパラメータの参照渡しは暗黙的に行われます(つまり、PHPは「後ろに」参照渡しを使用しています)。
3
AlterPHP

これは開発者の単なる選択であり、言語とは何の関係もないと思います。たくさんのPHPコード(組み込みおよび非組み込み)コードが参照を使用しています。PHPの配列関数を見てください。それらの多くは参照を使用しています。preg_matchは参照を使用しています。

開発者が参照を使用しないことを選択した理由の1つは、混乱を招く可能性があるためです。関数を呼び出すと、変数の1つが参照であるため、更新される場合と更新されない場合があります。したがって、デバッグするときに、$x jsutの値が魔法のように変更された理由が明確でない場合があります。

2
Rocket Hazmat

あなたの質問の根本的な問題は、これがC++でも一般的であると想定していることです。そうではありません。私たちは出力パラメータが好きではなく、それらをできるだけ使用しません-それらはCスタイルのAPIで本当に一般的です。

1
DeadMG

私は多くのPHP関数を知っています preg_match() を見てください。 $matchesは参照渡しされます

参照により引数を取る関数を自分で作成する場合は、次の構文を使用します

function byref(&$a, &$b, $c) {
    $a += $c;
    $b += $c;
    return $a * $b;
}

$ aと$ bは参照によって渡されます$ cは値によって渡されます。

0
hek2mgl