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):
Standardmäßig werden Funktionsargumente als Wert übergeben (sodass der Wert des Arguments innerhalb der Funktion nicht außerhalb der Funktion geändert wird , wenn er geändert wird). Damit eine Funktion ihre Argumente ändern kann , müssen sie als Referenz übergeben werden .
Stellen Sie dem Argumentnamen in der Funktionsdefinition ein kaufmännisches Und (&) voran, damit ein Argument für eine Funktion immer als Referenz übergeben wird
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:
<?php
function readAndDoStuffWithAnArray($array)
{
return $array[0] + $array[1] + $array[2];
}
$x = array(1, 2, 3);
echo readAndDoStuffWithAnArray($x);
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"):
<?php
// filling an array with 10000 elements of int 1
// let's say it grabs 3 mb from your RAM
$x = array_fill(0, 10000, 1);
// pass by value, right? RIGHT?
function readArray($arr) { // <-- a new symbol (variable) gets created here
echo count($arr); // let's just read the array
}
readArray($x);
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 ):
<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840
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:
<?php
function printUsedMemory($arr)
{
$start_memory = memory_get_usage();
count($arr); // read
$x = $arr[0]; // read (+ minor assignment)
$arr[0] - $arr[1]; // read
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1); // this is 1331840 bytes
printUsedMemory($x);
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 wie 1331840
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:
<?php
function printUsedMemory($arr)
{
$start_memory = memory_get_usage();
$arr[0] = 1; // WRITE!
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1);
printUsedMemory($x);
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:
<?php
function printUsedMemory(&$arr) // <----- explicit, user-land, pass-by-reference
{
$start_memory = memory_get_usage();
$arr[0] = 1; // WRITE!
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1);
printUsedMemory($x);
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 .