2013-08-11 41 views
9

In einer Blog-Post "PHP Internals: When does foreach copy", erklärte Nikić, dass, wie dies in einem Code:Warum kopiert foreach das Array, wenn wir es nicht in der Schleife geändert haben?

Snippet 1

$array = range(0, 100000); 
foreach ($array as $key => $value) { 
    xdebug_debug_zval('array'); // array is not copied, only refcount is increased 
} 

foreach wird das Array nicht kopieren, weil das einzige, was foreach modifiziert über $array ist es intern Arrayzeiger.

Er erklärte auch, dass in einem Code wie folgt aus:

Snippet 2

$array = range(0, 100000); // line 1 
test($array); 
function test($array) { 
    foreach ($array as $key => $value) { // line 4 
     xdebug_debug_zval('array'); // array is copied, refcount not increased 
     // ... 
    } 
} 

foreach das Array kopiert werden, denn wenn es nicht der Fall war, die $array Variable in Zeile 1 geändert werden würde .

jedoch das einzige, was foreach modifiziert über $array ist es Zeiger interne Array ist. Also warum ist es wichtig, wenn der interne Array-Zeiger der $array Variable in Zeile 1 geändert wird? In Snippet 1 spielte es keine Rolle, warum spielte es in Snippet 2 eine Rolle?

Warum muss foreach das Array in Snippet 2 kopieren, obwohl wir es nicht in der Schleife geändert haben?

+1

Von dem, was ich weiß, ist, dass konnte nicht viel, Sie Array immer als Kopie ist vorbei, weil Sie es als Referenz nicht sind vorbei. – JorgeeFG

+1

@Jorge, der Punkt ist, warum php nur weich kopiert (refcount erhöhen) in Schnipsel 1, aber hart in Schnipsel 2 kopiert? Warum können wir nicht auch in Snippet 2 kopieren, da es keine Änderungen am Array gibt? – Pacerier

+0

@Pacerier http://php.net/manual/en/language.references.pass.php –

Antwort

1

Ihre Frage wird in dem Artikel beantwortet, den Sie verlinkt haben. Es ist in dem,

Nicht referenzierte Abschnitt gegeben refcount> 1

mit der Erklärung, dass eine Kopie der Strukturen weil die Array-Zeiger bewegt benötigt wird, und dies kann die außen nicht beeinflussen muß Array.

+1

Können Sie ein Beispiel zeigen, wie es scheitern kann? Warum ist es wichtig, ob sich der interne Zeiger des äußeren Arrays ändert? Im ersten Snippet bewegt sich auch der Array-Zeiger, der dort keine Hardcopy vorschreibt. – Pacerier

+0

Wenn Sie einer Funktion eine Variable zuweisen, erwarten Sie, dass die Variable unverändert bleibt, nachdem die Funktion zurückgegeben wurde. Das Ändern des Array-Pointers ist auch eine Änderung der Variablen und das darf nicht passieren! – Sven

+1

Sie sagen, die Änderung des internen Array-Pointer ist auch eine Änderung der Variablen. Warum erstellt das erste Snippet keine Hardcopy? Das erste Snippet ändert auch das Array. Der Zustand von '$ array' vor dem' foreach' und nach dem 'foreach' ist im ersten Ausschnitt ebenfalls unterschiedlich. – Pacerier

1

Das liegt daran, dass im zweiten Fall $ array als Wert an die Funktion test() übergeben wird. Daher wurde eine Kopie des $ Arrays innerhalb der Funktion erstellt, und die foreach() funktioniert auf der Kopie. Die Dinge werden anders sein, wenn das $ Array durch Verweis auf die Funktion test() übergeben wird.

Informationen zu Pass von Wert vs Pass von Referenz, see this question

+1

Eine Hardcopy von '$ array' wurde nicht innerhalb der Funktion http://derickrethans.nl/talks/phparch-php-variables-article.pdf gemacht. Nur der Refcount erhöht sich wie von 'xdebug_debug_zval' gemeldet. Die 'foreach' funktioniert nicht auf der Kopie, da keine Kopie erstellt wurde. – Pacerier