Frage

Wenn Sie ein array übergeben wird, als argument an eine Methode oder Funktion ist es per Referenz übergeben?

Was ist zu tun:

$a = array(1,2,3);
$b = $a;

Ist $b ein Verweis auf $a?

War es hilfreich?

Lösung

Für den zweiten Teil Ihrer Frage finden Sie in der Array Seite des Handbuchs , die Zustände (Zitat) :

  

Array Zuordnung ist immer Wert   Kopieren. Die Referenz Operator   Kopieren eines Arrays Bezug genommen wird.

Und das gegebene Beispiel:

<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
             // $arr1 is still array(2, 3)

$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>


Für den ersten Teil, der beste Weg, um sicher zu sein, ist zu versuchen; -)

Betrachten Sie dieses Beispiel Code:

function my_func($a) {
    $a[] = 30;
}

$arr = array(10, 20);
my_func($arr);
var_dump($arr);

Es wird diese Ausgabe geben:

array
  0 => int 10
  1 => int 20

, die die Funktion gibt nicht die „außerhalb“ Array modifiziert, die als Parameter übergeben wurde. Es ist, als eine Kopie übergeben, und nicht eine Referenz

Wenn Sie es als Referenz übergeben wollen, müssen Sie die Funktion ändern müssen, auf diese Weise:

function my_func(& $a) {
    $a[] = 30;
}

Und der Ausgang werden:

array
  0 => int 10
  1 => int 20
  2 => int 30

Wie dieser Zeit hat sich das Array "by reference" übergeben worden ist.


Zögern Sie nicht, die Referenzen Abschnitt des Handbuchs erklärt zu lesen: es sollte antworten einige Ihrer Fragen; -)

Andere Tipps

Mit Bezug auf Ihre erste Frage wird das Array als Referenz übergeben, wenn sie innerhalb der Methode / Funktion Sie aufrufen geändert wird. Wenn Sie das Array innerhalb der Methode / Funktion zu ändern versuchen, eine Kopie davon gemacht wird zuerst, und dann nur die Kopie geändert wird. Dies macht es den Anschein, als ob der Array von Wert übergeben wird, wenn in der Tat ist es nicht.

Zum Beispiel, in diesem ersten Fall, auch wenn Sie nicht die Definition Ihre Funktion sind $ my_array unter Bezugnahme auf accept (durch das Zeichen & in der Parameterdefinition verwendet wird), ist es immer noch als Referenz übergeben wird (dh: Sie don‘ t Abfall-Speicher mit einer unnötigen Kopie).

function handle_array($my_array) {  

    // ... read from but do not modify $my_array
    print_r($my_array);

    // ... $my_array effectively passed by reference since no copy is made
}

Wenn Sie jedoch das Array ändern, eine Kopie davon gemacht erste (die mehr Speicher verwendet aber läßt Ihre ursprüngliche Array nicht betroffen).

function handle_array($my_array) {

    // ... modify $my_array
    $my_array[] = "New value";

    // ... $my_array effectively passed by value since requires local copy
}

FYI -. Dies wird als "lazy Kopie" bekannt oder "copy-on-write"

TL; DR

a) die Methode / Funktion liest nur das Array Argument => implizite (intern) Referenz
b) die Methode / Funktion ändert das Array Argument => Wert
c) die Methode / Funktion Array Argument wird ausdrücklich als Referenz markiert (mit einem Ampersand) => explizite (Benutzer-land) Referenz

Oder diese:
- Nicht-Et-Zeichen-Array param : Referenz zu übergeben; die Schreibvorgänge ändern, um eine neue Kopie des Arrays, zu kopieren, die auf dem ersten Schreib erstellt wird;
- Ampersand Array param : Referenz zu übergeben; Die Schreibvorgänge verändern den ursprünglichen Arrays.

Denken Sie daran - PHP hat einen Wert-Kopie , sobald Sie schreiben auf die Nicht-Et-Zeichen-Array param. Das ist, was copy-on-write Mittel. Ich würde gerne Sie die C-Quelle dieses Verhalten zeigen, aber es ist unheimlich da drin. Bessere Nutzung xdebug_debug_zval () .

Pascal MARTIN war richtig. Kosta Konto war sogar noch mehr.

Antwort

Es hängt davon ab.

Langfassung

Ich glaube, ich schreibe diese nach unten für mich. Ich sollte ein Blog oder etwas ...

Jedes Mal, wenn Menschen von Referenzen sprechen (oder Zeiger, für diese Angelegenheit), sie in der Regel in einem Logomachy am Ende (nur Blick auf diesem Thread !).
PHP eine ehrwürdige Sprache zu sein, ich dachte, dass ich die Verwirrung soll (obwohl dies eine Zusammenfassung der oben genannten Antworten). Denn obwohl zwei Personen zur gleichen Zeit richtig sein können, sind Sie besser dran, nur Knacken der Köpfe zusammen in eine Antwort.

Zunächst einmal, Sie sollten wissen, dass Du bist kein Pedant, wenn Sie in einer schwarz-weißen Art und Weise nicht beantworten . Die Dinge sind komplizierter als „ja / nein“.

Wie Sie sehen werden, das Ganze durch Wert / by-reference Sache ist sehr viel in Bezug auf was genau Sie mit diesem Array in Ihrer Methode / Funktionsumfang tun: lesen oder es zu ändern

Was sagt PHP? (Auch bekannt als "change-weise")

Das Handbuch sagt diese (Hervorhebung von mir):

  

In der Standardeinstellung Funktionsargumente sind als Wert übergeben (so dass, wenn die   Wert des Arguments in der Funktion geändert , ist es nicht bekommen   veränderte außerhalb der Funktion). Damit eine Funktion zu ändern seine   Argumente, müssen sie übergeben durch Verweis sein.

     

Um ein Argument an eine haben   Funktion immer als Referenz übergeben, prepend ein Und-Zeichen (& amp;) zu der   Argument Name in der Funktionsdefinition

Soweit ich das beurteilen kann, wenn große, ernst, ehrlich zu Gott Programmierer über Referenzen sprechen, sie in der Regel über Ändern Sie den Wert des Bezugs sprechen. Und das ist genau das, was die manuelle spricht über:. hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"

Es gibt einen weiteren Fall, dass sie nicht erwähnen, aber: was ist, wenn ich etwas nicht ändern - lesen Sie einfach
? Was passiert, wenn Sie ein Array an eine Methode übergeben, die einen Verweis nicht explizit Marken, und wir wissen nicht, dass Array in der Funktion Umfang ändern? Z.

<?php
function readAndDoStuffWithAnArray($array) 
{
    return $array[0] + $array[1] + $array[2];
}

$x = array(1, 2, 3);

echo readAndDoStuffWithAnArray($x);

Lesen Sie auf, meine Mitläufer.

Was ist PHP eigentlich? (Auch bekannt als "memory-wise")

Der gleiche große und schwerer Programmierer, wenn sie noch ernster zu bekommen, sprechen sie über „Memory-Optimierungen“ in Bezug auf Referenzen. Das Gleiche gilt für PHP. Da PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting, das ist warum .

Es wäre nicht ideal riesig Arrays, um verschiedene Funktionen zu übergeben, und PHP Kopien von ihnen zu machen (das ist, was „Pass-by-value“ der Fall ist, nachdem alle):

<?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);

Welljetzt, wenn dies tatsächlich Pass-by-Wert ist, möchten wir einig 3mb + RAM gegangen sind, weil es zwei Kopien des Arrays, nicht wahr?

Falsch. Solange wir die $arr Variable nicht ändern, die eine Referenz ist, Speicher-weise . Sie sehen es einfach nicht. Deshalb PHP erwähnt Benutzer-land Referenzen , wenn man über &$someVar sprechen, zwischen internen und explizit (mit Ampersand) zu unterscheiden.

Zahlen

So, when an array is passed as an argument to a method or function is it passed by reference?

ich kam mit drei (ja, drei) Fällen:
a) die Methode / Funktion liest nur , um das Array-Argument
b) die Methode / Funktion ändert das Array Argument
c) die Methode / Funktion Array-Argument ist explizit markiert als Referenz (mit einem Ampersand)


Zum einen wollen wir mal sehen, wie viel Speicher das Array tatsächlich eats (run hier ):

<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840

Dass viele Bytes. Toll.

a) die Methode / Funktion nur liest das Array-Argument

Lassen Sie uns nun eine Funktion machen die nur liest die das Array als Argument und wir werden sehen, wie viel Speicher die Leselogik nimmt:

<?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);

Wanna Vermutung? Ich erhalte 80! Überzeugen Sie sich selbst . Dies ist der Teil, dass die PHP-Handbuch auslässt. Wenn die $arr param tatsächlich bestanden-by-Wert wurde, würden Sie etwas Ähnliches wie 1331840 Bytes sehen. Es scheint, dass $arr verhält sich wie eine Referenz, nicht wahr? Das ist, weil es ein Referenz - ein internes eins.

b) die Methode / Funktion ändert das Array Argument

Nun lassen Sie uns write zu diesem param, statt von ihm 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, die ziemlich nah ist 1331840. in dieser So zu sein Fall das Array tatsächlich $arr kopiert werden.

c) die Methode / Funktion Array Argument wird ausdrücklich als Referenz markiert (mit einem Ampersand)

Nun wollen wir sehen, wie viel Speicher ein Schreibvorgang auf eine explizite Referenz nimmt (run hier ) - der Ampersand in der Funktionssignatur beachten Sie:

<?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 200 max bekommen! Also dieser eats etwa so viel Speicher wie aus einem Lesen nicht-Ampersand param .

In der Standardeinstellung

  1. Primitives werden von Wert übergeben. Einsatz unwahrscheinlich Java ist String primitiv in PHP
  2. Arrays von Primitiven werden von Wert übergeben
  3. Objekte sind vorbei Hinweis
  4. Arrays von Objekten Wert übergeben (das Array), aber jedes Objekt wird als Referenz übergeben.

    <?php
    $obj=new stdClass();
    $obj->field='world';
    
    $original=array($obj);
    
    
    function example($hello) {
        $hello[0]->field='mundo'; // change will be applied in $original
        $hello[1]=new stdClass(); // change will not be applied in $original
        $
    }
    
    example($original);
    
    var_dump($original);
    // array(1) { [0]=> object(stdClass)#1 (1) { ["field"]=> string(5) "mundo" } } 
    

Hinweis: Als Optimierung wird jeder einzelne Wert als Referenz übergeben, bis seine innerhalb der Funktion geändert. Wenn es geändert hat und der Wert wurde dann als Referenz übergeben, wird es kopiert und die Kopie geändert wird.

Wenn ein Array an einer Methode oder Funktion in PHP übergeben wird, ist es von Wert übergeben wird, wenn Sie es ausdrücklich durch Verweis übergeben, etwa so:

function test(&$array) {
    $array['new'] = 'hey';
}

$a = $array(1,2,3);
// prints [0=>1,1=>2,2=>3]
var_dump($a);
test($a);
// prints [0=>1,1=>2,2=>3,'new'=>'hey']
var_dump($a);

In Ihrer zweiten Frage ist $b kein Hinweis auf $a, sondern eine Kopie $a.

ähnlich wie das erste Beispiel, können Sie $a, indem Sie die folgenden Hinweis:

$a = array(1,2,3);
$b = &$a;
// prints [0=>1,1=>2,2=>3]
var_dump($b);
$b['new'] = 'hey';
// prints [0=>1,1=>2,2=>3,'new'=>'hey']
var_dump($a);

Dieser thread ist zwar schon etwas älter aber hier etwas, was ich kam gerade über:

Versuchen Sie diesen code:

$date = new DateTime();
$arr = ['date' => $date];

echo $date->format('Ymd') . '<br>';
mytest($arr);
echo $date->format('Ymd') . '<br>';

function mytest($params = []) {
    if (isset($params['date'])) {
        $params['date']->add(new DateInterval('P1D'));
    }
}

http://codepad.viper-7.com/gwPYMw

Hinweis: es ist kein amp für die $params-parameter-und noch ändert es den Wert von $arr['date'].Dies entspricht nicht ganz mit all den anderen Erklärungen hier, und was ich dachte, bis jetzt.

Wenn ich clone die $params['date'] Objekt, das 2. ausgegeben, das Datum bleibt gleich.Wenn ich nur setzen Sie es in eine Zeichenfolge, die es nicht Wirkung die Ausgabe entweder von sich aus.

In PHP Arrays werden standardmäßig Funktionen von Wert übergeben, wenn Sie sie nicht ausdrücklich als Verweis übergeben, wie die folgende Ausschnitt zeigt:

$foo = array(11, 22, 33);

function hello($fooarg) {
  $fooarg[0] = 99;
}

function world(&$fooarg) {
  $fooarg[0] = 66;
}

hello($foo);
var_dump($foo); // (original array not modified) array passed-by-value

world($foo);
var_dump($foo); // (original array modified) array passed-by-reference

Hier ist die Ausgabe:

array(3) {
  [0]=>
  int(11)
  [1]=>
  int(22)
  [2]=>
  int(33)
}
array(3) {
  [0]=>
  int(66)
  [1]=>
  int(22)
  [2]=>
  int(33)
}

Um eine der Antworten zu erweitern, auch Sub-Arrays von mehrdimensionalen Arrays von Wert übergeben werden, es sei denn bestanden ausdrücklich Bezug genommen wird.

<?php
$foo = array( array(1,2,3), 22, 33);

function hello($fooarg) {
  $fooarg[0][0] = 99;
}

function world(&$fooarg) {
  $fooarg[0][0] = 66;
}

hello($foo);
var_dump($foo); // (original array not modified) array passed-by-value

world($foo);
var_dump($foo); // (original array modified) array passed-by-reference

Das Ergebnis ist:

array(3) {
  [0]=>
  array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
  }
  [1]=>
  int(22)
  [2]=>
  int(33)
}
array(3) {
  [0]=>
  array(3) {
    [0]=>
    int(66)
    [1]=>
    int(2)
    [2]=>
    int(3)
  }
  [1]=>
  int(22)
  [2]=>
  int(33)
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top