Warum werden Referenzen in PHP selten verwendet?

26

Ich habe einige C ++ - Kenntnisse und weiß, dass dort häufig Zeiger verwendet werden, aber ich habe angefangen, mich mit PHP-Open-Source-Code zu befassen, und sehe keinen Code, der Referenzen in Methoden verwendet.

Stattdessen verwendet der Code immer einen Rückgabewert, anstatt den Verweis auf die Variable an die Methode zu übergeben. Diese ändert dann den Wert dieser Variablen und gibt ihn einfach zurück.

Ich habe gelesen, dass die Verwendung von Referenzen weniger Speicherplatz beansprucht. Warum werden sie in PHP nicht verwendet?

Alexander Cogneau
quelle
19
Die Verwendung von Pass-by-Reference-Parametern ist eine "Nebenwirkungsprogrammierung" - die Verwendung einer Funktion zum Zurückgeben eines einzelnen Werts ist beim Lesen von Code wesentlich deutlicher. Allerdings verwenden einige PHP-Kernfunktionen Referenzen.
Halfer
3
PHP übergibt Objekte standardmäßig als Referenz.
2
Array-Sortierungen sind ein Paradebeispiel für die wichtigsten PHP-Funktionen, die als Referenz dienen
Mark Baker
2
PHP-Referenzen sind keine Zeiger und sind oft ein Ärgernis, wenn Sie sie nicht genau dort erwarten, wo sie auftauchen.
Lanzz
2
Wenn Sie mehrere Rückgaben benötigen, return array($foo, $bar);undlist($A, $B) = foobar();
Izkata

Antworten:

49

Ihre Behauptung, dass Referenzen selten verwendet werden, ist falsch. Wie andere bereits erwähnt haben, gibt es eine Menge nativer Funktionen, die Referenzen verwenden. Bemerkenswerte Beispiele sind die Array-Sortierfunktionen und preg_match()/ preg_match_all(). Wenn Sie eine dieser Funktionen in Ihrem Code verwenden, verwenden Sie auch Verweise.

Weiter sind Referenzen in PHP keine Zeiger. Da Sie einen C ++ - Hintergrund haben, kann ich die Verwirrung verstehen, aber PHP-Referenzen sind ein ganz anderes Biest, sie sind Aliase für eine Symboltabelle . Leistungssteigerungen, die Sie von C ++ - Referenzen erwartet haben, gelten einfach nicht für PHP-Referenzen.

Tatsächlich ist die Übergabe von Werten in den meisten Szenarien schneller und weniger speicherintensiv als die Übergabe von Referenzen. Die Zend Engine, der Kern von PHP, verwendet einen Copy-on-Write- Optimierungsmechanismus, der keine Kopie einer Variablen erstellt, bis sie geändert wird. Das Übergeben von Referenzen unterbricht normalerweise das Copy-on-Write-Muster und erfordert eine Kopie, unabhängig davon, ob Sie den Wert ändern oder nicht.

Haben Sie keine Angst, Referenzen in PHP zu verwenden, wenn Sie dies benötigen, und versuchen Sie nicht nur, diese zu optimieren. Denken Sie daran, vorzeitige Optimierung ist die Wurzel allen Übels .

Weitere Lektüre:

yannis
quelle
Danke für die Korrektur @NikiC.
Etwas
Um die Antwort zu vervollständigen, wäre es schön darauf hinzuweisen, dass alle Objekte in PHP als Referenz übergeben werden.
Florian Margaine
@FlorianMargaine Das ist nicht ganz richtig (siehe zweiten Link in weiterer Lektüre).
Yannis
2
@FlorianMargaine Nein, die beiden sind sehr unterschiedlich und es ist wichtig zu verstehen, warum das so ist.
Phant0m
3
@FlorianMargaine Nein, suppose Objekte wurden durch Bezugnahme in PHP übergeben: f($obj)gegeben function f($x) { $x = new X; }, hätten $objzu einem beziehen anderes Objekt als vor dem Aufruf f(). Da Objekte jedoch nicht als Referenz übergeben werden, wird $ obj nicht geändert, wenn Sie dies mit PHP ausführen. Auf diese Weise macht PHP dasselbe wie Java.
Phant0m
8

PHP führt bereits eine Copy-on-Write-Funktion aus, bei der kein neuer Wert erstellt wird, bis Sie etwas ändern, sodass durch die Verwendung von Referenzen nicht viel Speicherplatz gespart wird. Dies kann sogar zu Problemen führen, die PHP intern verursacht, um die Speichernutzung zu verringern und die Situation noch schlimmer zu machen.

Hinzu kommt, dass Referenzen die Dinge im Allgemeinen etwas zu magisch machen. Der Standardwert und damit das, was die meisten Menschen erwarten, ist der Vorübergehender Wert. Wenn ich $izu einer Funktion übergehe , wird es enorm kompliziert, wenn ich mich darum kümmern muss, ob sich diese Funktion auf mysteriöse Weise $izu etwas anderem ändert , und auf diese Weise für alle Fälle defensive Kopien anfertigt. (Es kann bereits geändert werden, $iwenn der Wert ein Objekt ist, aber meiner Meinung nach sollte es nicht.)

Grundsätzlich würde ich nur Pass-by-reference nützlich finden für „out“ Parameter, dh Variablen i erwarten wieder aus der Funktion und nicht weiter in, a la preg_match‚s &$matches. Sogar für Funktionen, die das Objekt, in das übergeben wird , deutlich verändern, wie sortoder array_pop, fühlt sich das ein bisschen icky an ... aber das ist es, woran wir festhalten.

cHao
quelle
5

PHP ist eine weborientierte Sprache.
Webseiten werden schnell geliefert und sollten leicht sein.
Das übliche PHP-Programm ist im Bruchteil einer Sekunde aktiv und belegt einige hundert Kilobyte Speicher.
Für solche Optimierungen gibt es keine Verwendung.

Dein gesunder Menschenverstand
quelle
1
Dies. Benötigt keine Zeiger / Referenzen, da es nicht auf einer so niedrigen Ebene wie C ++ herumwirbelt.
Kenneth Worden
8
Warum wird dieser Beitrag 5+ ??? Es tut a) die Frage nicht beantworten b) ist nicht korrekt
1
Referenzen sind also langsam und verbrauchen zu viel Speicher?
Rocket Hazmat
1
@RocketHazmat Ja, seltsamerweise stimmt das.
Yannis
3

Einige Gründe im Fluge:

  • PHP ist eine Skriptsprache und zielt nicht darauf ab, als eingebettete Kernsoftware verwendet zu werden (im Grunde wird der Speicher am Ende des Skripts gelöscht).
  • Seit PHP5 ist Pass-by-Reference für Objektparameter implizit (daher verwendet PHP Pass-by-Reference "in your back").
AlterPHP
quelle
1
Siehe: php.net/manual/en/language.oop5.references.php für Ihren zweiten Punkt.
Yannis
2

Ich denke, das ist nur eine Wahl der Entwickler, nichts mit der Sprache zu tun. Viele PHP-Codes (eingebaute und nicht eingebaute) verwenden Referenzen. Werfen Sie einen Blick auf die Array-Funktionen in PHP, von denen viele Referenzen verwenden. preg_matchVerwendet Referenzen.

Ich denke, einer der Gründe, warum Entwickler keine Referenzen verwenden, ist, dass dies verwirrend sein kann. Sie rufen eine Funktion auf und eine der Variablen wird möglicherweise (oder möglicherweise nicht) aktualisiert, weil es sich um eine Referenz handelte. Wenn Sie also debuggen, ist möglicherweise nicht klar, warum sich der Wert von $xjsut magisch geändert hat.

Rocket Hazmat
quelle
1

Das grundlegende Problem bei Ihrer Frage ist, dass Sie davon ausgehen, dass dies auch in C ++ der Fall ist. Ist es nicht. Wir mögen Ausgabeparameter nicht und verwenden sie so wenig wie möglich. Sie sind nur in APIs im C-Stil üblich.

DeadMG
quelle
0

Ich kenne viele PHP-Funktionen, die dies tun. Schauen Sie sich preg_match()zum Beispiel an. $matcheswird als Referenz übergeben

Wenn Sie eine Funktion schreiben möchten, die Argumente als Referenz verwendet, verwenden Sie die folgende Syntax

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

$ a und $ b werden als Referenz übergeben. $ c wird als Wert übergeben.

hek2mgl
quelle