1) Wenn ein Array als Argument an eine Methode oder Funktion übergeben wird, wird es als Referenz oder als Wert übergeben?
2) Wenn Sie einer Variablen ein Array zuweisen, verweist die neue Variable auf das ursprüngliche Array oder handelt es sich um eine neue Kopie?
Was ist damit:
$a = array(1,2,3);
$b = $a;
Ist $b
ein Verweis auf $a
?
Antworten:
Den zweiten Teil Ihrer Frage finden Sie auf der Array-Seite des Handbuchs , auf der Folgendes angegeben ist (Zitat) :
Und das gegebene Beispiel:
Für den ersten Teil ist der beste Weg, um sicher zu sein, es zu versuchen ;-)
Betrachten Sie dieses Codebeispiel:
Es wird diese Ausgabe geben:
Dies zeigt an, dass die Funktion das als Parameter übergebene "externe" Array nicht geändert hat: Es wird als Kopie und nicht als Referenz übergeben.
Wenn Sie möchten, dass es als Referenz übergeben wird, müssen Sie die Funktion folgendermaßen ändern:
Und die Ausgabe wird:
Da dieses Mal das Array "als Referenz" übergeben wurde.
Zögern Sie nicht, den Abschnitt " Erklärte Referenzen " des Handbuchs zu lesen : Er sollte einige Ihrer Fragen beantworten ;-)
quelle
&
, sollte es - siehe php.net/manual/en/…In Bezug auf Ihre erste Frage wird das Array als Referenz übergeben, sofern es nicht innerhalb der von Ihnen aufgerufenen Methode / Funktion geändert wird. Wenn Sie versuchen, das Array innerhalb der Methode / Funktion zu ändern, wird zuerst eine Kopie davon erstellt, und dann wird nur die Kopie geändert. Dies lässt es so aussehen, als ob das Array als Wert übergeben wird, obwohl dies tatsächlich nicht der Fall ist.
In diesem ersten Fall wird Ihre Funktion zwar nicht so definiert, dass sie $ my_array als Referenz akzeptiert (indem Sie das Zeichen & in der Parameterdefinition verwenden), sie wird jedoch weiterhin als Referenz übergeben (dh Sie verschwenden keinen Speicher mit einer unnötigen Kopie).
Wenn Sie das Array jedoch ändern, wird zuerst eine Kopie davon erstellt (die mehr Speicher benötigt, Ihr ursprüngliches Array jedoch nicht beeinflusst).
Zu Ihrer Information - dies ist als "Lazy Copy" oder "Copy-on-Write" bekannt.
quelle
TL; DR
a) Die Methode / Funktion liest nur das Array-Argument => implizite (interne) Referenz
b) Die Methode / Funktion ändert das Array-Argument => Wert
c) Das Methode / Funktion-Array-Argument wird explizit als Referenz markiert (mit einem kaufmännischen Und). => explizite (Benutzerland-) Referenz
Oder dies:
- Array-Parameter ohne kaufmännisches Und : als Referenz übergeben; Die Schreibvorgänge ändern eine neue Kopie des Arrays, eine Kopie, die beim ersten Schreiben erstellt wird.
- kaufmännisches Und-Array-Parameter : als Referenz übergeben; Die Schreibvorgänge ändern das ursprüngliche Array.
Denken Sie daran, dass PHP in dem Moment, in dem Sie in den Array-Parameter ohne kaufmännisches Und schreiben , eine Wertkopie erstellt. Das
copy-on-write
heißt was . Ich würde Ihnen gerne die C-Quelle dieses Verhaltens zeigen, aber es ist dort beängstigend. Verwenden Sie besser xdebug_debug_zval () .Pascal MARTIN hatte recht. Kosta Kontos war es noch mehr.
Antworten
Es hängt davon ab, ob.
Lange Version
Ich glaube, ich schreibe das für mich auf. Ich sollte einen Blog haben oder so ...
Wenn Leute von Referenzen (oder Zeigern) sprechen, geraten sie normalerweise in eine Logomachie (schauen Sie sich nur diesen Thread an !).
Da PHP eine ehrwürdige Sprache ist, dachte ich, ich sollte die Verwirrung noch verstärken (obwohl dies eine Zusammenfassung der obigen Antworten ist). Denn obwohl zwei Personen gleichzeitig Recht haben können, ist es besser, wenn Sie nur ihre Köpfe zu einer Antwort zusammenbrechen.
Zunächst sollten Sie wissen, dass Sie kein Pedant sind, wenn Sie nicht schwarz-weiß antworten . Die Dinge sind komplizierter als "Ja / Nein".
Wie Sie sehen werden, hängt die gesamte Sache nach Wert / Referenz sehr stark davon ab, was genau Sie mit diesem Array in Ihrem Methoden- / Funktionsumfang tun: Lesen oder Ändern?
Was sagt PHP? (auch bekannt als "veränderungsmäßig")
Das Handbuch sagt dies (Hervorhebung von mir):
Soweit ich das beurteilen kann, sprechen große, seriöse und ehrliche Programmierer, wenn sie über Referenzen sprechen, normalerweise davon , den Wert dieser Referenz zu ändern . Und genau darüber spricht das Handbuch :
hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.Es gibt noch einen anderen Fall, den sie nicht erwähnen: Was ist, wenn ich nichts ändere - einfach lesen?
Was passiert, wenn Sie ein Array an eine Methode übergeben, die keine Referenz explizit markiert, und wir dieses Array im Funktionsumfang nicht ändern? Z.B:
Lesen Sie weiter, mein Mitreisender.
Was macht PHP eigentlich? (auch bekannt als "gedächtnismäßig")
Dieselben großen und seriösen Programmierer sprechen, wenn sie noch ernsthafter werden, von "Speicheroptimierungen" in Bezug auf Referenzen. PHP auch. Weil
PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
, das ist , warum .Es wäre nicht ideal, RIESIGE Arrays an verschiedene Funktionen zu übergeben und PHP, um Kopien davon zu erstellen (genau das macht schließlich "Pass-by-Value"):
Nun, wenn dies tatsächlich ein Pass-by-Wert wäre, hätten wir 3 MB + RAM verloren, weil es zwei Kopien dieses Arrays gibt, oder?
Falsch. Solange wir die
$arr
Variable nicht ändern , ist dies eine Referenz in Bezug auf den Speicher . Du siehst es einfach nicht. Deshalb PHP erwähnt benutzer Land Referenzen , wenn es um Gespräche&$someVar
zwischen internen und explizit (mit Ampersand) zu unterscheiden.Fakten
So,
when an array is passed as an argument to a method or function is it passed by reference?
Ich habe drei (ja, drei) Fälle gefunden:
a) Die Methode / Funktion liest nur das Array-Argument.
B) Die Methode / Funktion ändert das Array-Argument.
C) Das Array-Argument der Methode / Funktion ist explizit als Referenz markiert (mit einem Et-Zeichen)
Lassen Sie uns zunächst sehen, wie viel Speicher das Array tatsächlich verbraucht ( hier ausführen ):
So viele Bytes. Toll.
a) Die Methode / Funktion liest nur das Array-Argument
Lassen Sie uns nun eine Funktion erstellen, die nur das Array als Argument liest , und wir werden sehen, wie viel Speicher die Leselogik benötigt:
Willst du raten? Ich bekomme 80! Überzeugen Sie sich selbst . Dies ist der Teil, den das PHP-Handbuch weglässt. Wenn der
$arr
Parameter tatsächlich als Wert übergeben wurde, sehen Sie etwas Ähnliches wie1331840
Bytes. Es scheint, dass$arr
sich das wie eine Referenz verhält, nicht wahr? Das liegt daran, dass es sich um eine interne Referenz handelt.b) Die Methode / Funktion ändert das Array-Argument
Schreiben wir nun an diesen Parameter, anstatt daraus zu lesen:
Auch hier sehen Sie selbst , aber für mich, dass in diesem Fall zu sein 1331840. So ziemlich nah dran ist, das Array ist tatsächlich kopiert werden
$arr
.c) Das Argument für das Methoden- / Funktionsarray wird explizit als Referenz markiert (mit einem kaufmännischen Und).
Lassen Sie uns nun sehen, wie viel Speicher eine Schreiboperation für eine explizite Referenz benötigt ( hier ausführen ). Beachten Sie das kaufmännische Und in der Funktionssignatur:
Meine Wette ist, dass Sie maximal 200 bekommen! Dies verbraucht also ungefähr so viel Speicher wie das Lesen von einem Parameter ohne kaufmännisches Und .
quelle
Standardmäßig
Arrays von Objekten werden als Wert (das Array) übergeben, aber jedes Objekt wird als Referenz übergeben.
Hinweis: Als Optimierung wird jeder einzelne Wert als Referenz übergeben, bis er innerhalb der Funktion geändert wird. Wenn es geändert wurde und der Wert als Referenz übergeben wurde, wird es kopiert und die Kopie wird geändert.
quelle
Wenn ein Array an eine Methode oder Funktion in PHP übergeben wird, wird es als Wert übergeben, es sei denn, Sie übergeben es explizit als Referenz, wie folgt:
In Ihrer zweiten Frage
$b
handelt es sich nicht um einen Verweis auf$a
, sondern um eine Kopie von$a
.Ähnlich wie im ersten Beispiel können Sie auf
$a
Folgendes verweisen :quelle
Dieser Thread ist etwas älter, aber hier ist mir etwas begegnet:
Versuchen Sie diesen Code:
http://codepad.viper-7.com/gwPYMw
Beachten Sie, dass für den Parameter $ params kein Verstärker vorhanden ist und der Wert von $ arr ['date'] geändert wird. Dies stimmt nicht wirklich mit allen anderen Erklärungen hier und dem überein, was ich bisher gedacht habe.
Wenn ich das Objekt $ params ['date'] klone, bleibt das 2. ausgegebene Datum gleich. Wenn ich es nur auf einen String setze, wirkt sich das auch nicht auf die Ausgabe aus.
quelle
Um eine der Antworten zu erweitern, werden auch Subarrays mehrdimensionaler Arrays als Wert übergeben, sofern sie nicht explizit als Referenz übergeben werden.
Das Ergebnis ist:
quelle
In PHP werden Arrays standardmäßig standardmäßig an Funktionen übergeben, es sei denn, Sie übergeben sie explizit als Referenz, wie das folgende Snippet zeigt:
Hier ist die Ausgabe:
quelle