Frage

Ich stelle diese Frage, weil ich gelernt habe, dass Sie bei der Programmierung und Gestaltung einen guten Grund für Entscheidungen haben müssen. Ich lerne PHP und ich bin hier an einem Scheideweg. Ich verwende eine einfache Inkrementierung, um zu versuchen, das zu bekommen, was ich frage. Ich bin sicherlich nicht hier, um eine Debatte über die Vor-/Nachteile der Referenzierung zu beginnen, aber wenn es um PHP geht, ist dies die bessere Programmierungspraxis:

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

vs.

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

$param = increment($param);
War es hilfreich?

Lösung

Zuerst, Referenzen sind keine Zeiger.

Ich habe den Code von @john in seiner Antwort ausprobiert, aber ich bekam seltsame Ergebnisse. Es stellt sich heraus microtime() Gibt eine Zeichenfolge zurück. Die Arithmetik ist unzuverlässig und ich habe in einigen Läufen sogar negative Ergebnisse erzielt. Man sollte verwenden microtime(true) Um den Wert als Schwimmer zu erhalten.

Ich habe einen weiteren Test ohne Funktionsaufruf hinzugefügt, nur die Variable zu erhöhen:

<?php

$param = 1;

$start = microtime(true);

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

$end = microtime(true);

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

Die Ergebnisse auf meiner Maschine, MacBook 2.4GHz, läuft PHP 5.3.2.

  • Funktionsaufruf mit PASSION BY REFERENZ: 2.14 Sek.
  • Funktionsaufruf mit Pass nach Wert: 2,26 Sek.
  • Kein Funktionsaufruf, nur bloßes Inkrement: 0,42 Sek.

Es scheint also einen Leistungsvorteil von 5,3% für die Übergabe von Referenz zu geben, aber es gibt einen Leistungsvorteil von 81%, um den Funktionsaufruf vollständig zu vermeiden.

Ich denke, das Beispiel für die Inkrementierung einer Ganzzahl ist willkürlich, und das OP fragt wirklich nach dem allgemeinen Vorteil des Übergangs von Referenz. Aber ich biete dieses Beispiel nur an, um das zu demonstrieren Der Funktionsaufruf allein verursacht weitaus mehr Overhead als die Methode zum Übergeben von Parametern.

Wenn Sie also versuchen, zu entscheiden, wie Sie den Parameter vor dem Mikro-optimieren, sind Sie pennig weise und dumm.

Es gibt auch andere Gründe, warum Sie Referenzen vermeiden sollten. Obwohl sie mehrere Algorithmen vereinfachen können, insbesondere wenn Sie zwei oder mehr Datenstrukturen manipulieren, die die gleichen zugrunde liegenden Daten haben müssen:

  • Sie machen Funktionen haben Nebenwirkungen. Sie sollten im Allgemeinen Funktionen mit Nebenwirkungen vermeiden, da es das Programm unvorhersehbarer macht (wie in "OK, wie ist dieser Wert hierher? Hat eine der Funktionen seine Parameter geändert?")
  • Sie verursachen Käfer. Wenn Sie eine Variable zu einer Referenz machen, müssen Sie sich daran erinnern, sie zu verunsichern, bevor Sie ihr einen Wert zuweisen, es sei denn, Sie möchten den zugrunde liegenden Wert des Referenzsatzes ändern. Dies geschieht häufig, nachdem Sie eine Foreach-Schleife durch Referenz ausgeführt und dann die Schleifenvariable wiederverwenden.

Andere Tipps

Es hängt davon ab, was der Zweck der Funktionen ist. Wenn sein ausdrücklicher Zweck darin besteht, die Eingabe zu ändern, verwenden Sie Referenzen. Wenn der Zweck darin besteht, einige Daten basierend auf der Eingabe zu berechnen und nicht Um die Eingabe zu ändern, verwenden Sie auf jeden Fall einen regulären return.

Nehmen Sie zum Beispiel array_push:

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

Der ausdrückliche Zweck dieser Funktion besteht darin, ein Array zu ändern. Es ist unwahrscheinlich, dass Sie sowohl das ursprüngliche Array als auch eine Kopie davon einschließlich der Pushed -Werte benötigen.

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

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

Wenn array_push Ich müsste dies nicht erledigen: Sie müssten dies tun:

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

Andererseits eine rein rechnerische Funktion wie pow sollte den ursprünglichen Wert nicht ändern:

number pow(number $base, number $exp)

Sie verwenden diese Funktion wahrscheinlich eher in einem Kontext, in dem Sie die ursprüngliche Nummer intakt halten und einfach ein Ergebnis basierend darauf berechnen möchten. In diesem Fall wäre es ein Ärgernis, wenn pow modifizierte die ursprüngliche Nummer.

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

Wenn pow Referenzen haben, Sie müssten dies tun:

// pow(&$base, $exp)
$x = 123;
$y = $x; // nuisance
pow($y, 42);

Die beste Praxis ist nicht, eine Funktion zu schreiben, wenn ein Ausdruck ausfällt.

$param++;

ist alles, was du brauchst.

Die zweite Version:

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

$param = increment($param);

Tut nichts. Increment () gibt $ param zurück. Vielleicht haben Sie ++ $ param oder $ param+1 gemeint;

Ich erwähne, dass dies nicht pedantisch sein soll, aber damit Sie die gleiche Funktion vergleichen, wenn Sie die Timings vergleichen (es kann möglich sein, dass der Optimierer von PHP die Funktion vollständig entfernt).

Per Definition mutiert die Inkrementierung des Werts einer Variablen (zumindest in PHP) die Variable. Es braucht keinen Wert, erhöht ihn um 1 und gibt es zurück; Vielmehr ändert es die Variable, die diesen Wert hält.

Ihr erstes Beispiel wäre also der bessere Weg zu gehen, da es eine Referenz nimmt (PHP macht keine Zeiger an sich) von $param und nach der Inkrementierung.

Ich habe gerade ein paar schnelle Tests mit dem folgenden Code durchgeführt:

<?php

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

$start = microtime();

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

$end = microtime();

echo $end - $start;

?>

Dies kehrte konsequent zwischen 0,42 bis 0,43 zurück, wobei der folgende Code etwa 0,55 bis 0,59 zurückgab

<?php

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

$start = microtime();

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

$end = microtime();

echo $end - $start;

?>

Ich würde also sagen, dass die Referenzen schneller sind, aber nur in extremen Fällen.

Ich denke, Ihr Beispiel ist ein wenig abstrakt.

Bei der Verwendung von Zeigern besteht kein Problem, aber in den meisten Fällen in der realen Welt ändern Sie wahrscheinlich ein Objekt, das nicht in INT ist. In diesem Fall benötigen Sie die Referenz nicht (zumindest in PHP5).

Ich würde sagen, es würde ganz davon abhängen, was Sie tun. Wenn Sie versuchen, mit einem großen Datensatz zu interagieren, ohne eine zusätzliche Kopie davon im Speicher zu wünschen, gehen Sie nach Wert (Ihr zweites Beispiel). Wenn Sie den Speicher speichern und direkt mit einem Objekt interagieren möchten - übergeben Sie nach Referenz (Ihr erstes Beispiel)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top