4

私がこの質問をするのは、プログラミングと設計において、あなたには決定の正当な理由がなければならないことを知ったからです。私はphp学習者であり、ここで岐路に立っています。単純なインクリメントを使用して、私が求めているものを取得しようとしています。私は確かに参照の賛否両論について議論を始めるためにここにいるわけではありませんが、phpに関しては、より良いプログラミング手法です:

function increment(&$param) {
      ++$param;
}

対。

function increment($param){
 return ++$param;
}

$param = increment($param);
4

8 に答える 8

10

まず、参照はポインタではありません

@Johnの回答で与えられたコードを試しましたが、奇妙な結果が得られました。microtime()文字列を返すことがわかりました。算術演算は信頼性が低く、一部の実行で否定的な結果が得られました。microtime(true)値をfloatとして取得するために使用する必要があります。

変数をインクリメントするだけで、関数呼び出しなしの別のテストを追加しました。

<?php

$param = 1;

$start = microtime(true);

for($i = 1; $i <= 1000000; $i++) {
    $param++;
}

$end = microtime(true);

echo "increment: " . ($end - $start) . "\n";

私のマシン、PHP5.3.2を実行しているMacbook2.4GHzでの結果。

  • 参照渡しを使用した関数呼び出し:2.14秒。
  • 値渡しによる関数呼び出し:2.26秒。
  • 関数呼び出しなし、わずかな増分:0.42秒。

したがって、参照渡しには5.3%のパフォーマンス上の利点があるように見えますが、関数呼び出しを完全に回避することには81%のパフォーマンス上の利点があります。

整数をインクリメントする例は任意だと思いますが、OPは実際に参照渡しの一般的な利点について質問しています。ただし、この例を提供しているのは、関数呼び出しだけで、パラメーターを渡す方法よりもはるかに多くのオーバーヘッドが発生することを示しています。

したがって、パラメーターの受け渡しをマイクロ最適化する方法を決定しようとしている場合は、ペニー賢く、ポンド愚かです。

参照を避けるべき理由は他にもあります。特に、同じ基になるデータを持つ必要がある2つ以上のデータ構造を操作する場合は、いくつかのアルゴリズムを単純化できますが、次のようになります。

  • それらは関数に副作用を持たせます。一般に、副作用のある関数はプログラムを予測不可能にするため、避ける必要があります(「OK、この値はどのようにしてここに到達したのですか?関数のいずれかがパラメーターを変更しましたか?」のように)
  • それらはバグを引き起こします。変数を参照にする場合は、参照セットの基になる値を変更する場合を除いて、値を割り当てる前に変数の設定を解除することを忘れないでください。これは、参照によってforeachループを実行し、ループ変数を再利用した後に頻繁に発生します。
于 2010-06-03T01:01:07.980 に答える
3

それは機能の目的が何であるかに依存します。その明確な目的が入力を変更することである場合は、参照を使用してください。入力に基づいて一部のデータを計算することが目的であり、入力を変更しないことが目的である場合は、必ず通常のを使用してreturnください。

たとえばarray_push

int array_push(array &$array, mixed $var[, mixed $...])

この関数の明確な目的は、配列を変更することです。元の配列と、プッシュされた値を含むそのコピーの両方が必要になる可能性はほとんどありません。

array_push($array, 42); // most likely use case

// if you really need both versions, just do:
$old = $array;
array_push($array, 42);

参照を取得しなかった場合array_pushは、次のようにする必要があります。

// array_push($array, $var[, $...])
$array = array_push($array, 42); // quite a waste to do this every time

一方、のような純粋な計算関数powは、元の値を変更しないでください。

number pow(number $base, number $exp)

この関数は、元の数値をそのまま維持し、それに基づいて結果を計算する場合に使用する可能性が高くなります。この場合pow、元の番号を変更すると迷惑になります。

$x = 123;
$y = pow($x, 42); // most likely use case

参照を取得した場合powは、これを行う必要があります。

// pow(&$base, $exp)
$x = 123;
$y = $x; // nuisance
pow($y, 42);
于 2010-06-03T01:21:31.637 に答える
2

ベストプラクティスは、式が実行されるときに関数を記述しないことです。

$param++;

は、あなたが必要とすることすべてです。

于 2010-06-03T00:39:18.320 に答える
2

2番目のバージョン:

function increment($param){
 return $param++;
}

$param = increment($param);

何もしません。incremental()は$paramを返します。おそらくあなたは++$paramまたは$param+1を意味しました。

これは衒学的ではないことを述べていますが、タイミングを比較すると、同じ関数を比較していることになります(PHPのオプティマイザーが関数を完全に削除する可能性があります)。

于 2010-06-03T01:57:28.843 に答える
1

定義上、(少なくともPHPでは)変数の値をインクリメントすると、変数が変化します。値を取りません。値を1増やして返します。むしろ、その値を保持している変数を変更します。

したがって、最初の例は、参照を取得し(PHP自体は実際にはポインターを実行しません)$param、ポストインクリメントするため、より適切な方法になります。

于 2010-06-03T00:34:09.053 に答える
1

次のコードを使用して、いくつかの簡単なテストを実行しました。

<?php

function increment(&$param){
 $param++;
}
$param = 1;

$start = microtime();

for($i = 1; $i <= 1000000; $i++) {
    increment($param);
}

$end = microtime();

echo $end - $start;

?>

これは、一貫して約.42から.43に戻りましたが、次のコードは約.55から.59に戻りました。

<?php

function increment($param){
 return $param++;
}
$param = 1;

$start = microtime();

for($i = 1; $i <= 1000000; $i++) {
    $param = increment($param);
}

$end = microtime();

echo $end - $start;

?>

したがって、参照はより高速ですが、極端な場合に限られます。

于 2010-06-03T00:35:41.497 に答える
0

あなたの例は少し抽象的なものだと思います。

ポインタの使用に問題はありませんが、実際のほとんどの場合、intではなくオブジェクトを変更している可能性があります。その場合、参照は必要ありません(少なくともPHP5では)。

于 2010-06-03T00:38:58.543 に答える
0

それはあなたがしていることにかなり依存すると思います。メモリ内にデータの余分なコピーを必要とせずに大量のデータセットを操作しようとしている場合は、先に進み、値を渡します(2番目の例)。メモリを節約し、オブジェクトを直接操作する場合-参照渡し(最初の例)

于 2010-06-03T00:40:38.350 に答える