TL; DR
a) la méthode / fonction lit uniquement l'argument tableau => référence implicite (interne)
b) la méthode / fonction modifie l'argument tableau => valeur
c) l'argument méthode / fonction tableau est explicitement marqué comme référence (avec une esperluette) => référence explicite (user-land)
Ou ceci:
- paramètre de tableau non-esperluette : passé par référence; les opérations d'écriture modifient une nouvelle copie du tableau, copie qui est créée lors de la première écriture;
- paramètre de tableau esperluette : transmis par référence; les opérations d'écriture modifient le tableau d'origine.
N'oubliez pas - PHP effectue une copie de valeur au moment où vous écrivez dans le paramètre du tableau non esperluette. Voilà ce que ça copy-on-write
veut dire. J'adorerais vous montrer la source C de ce comportement, mais c'est effrayant là-dedans. Mieux vaut utiliser xdebug_debug_zval () .
Pascal MARTIN avait raison. Kosta Kontos l'était encore plus.
Répondre
Ça dépend.
Version longue
Je pense que je l'écris pour moi. Je devrais avoir un blog ou quelque chose ...
Chaque fois que les gens parlent de références (ou de pointeurs, d'ailleurs), ils se retrouvent généralement dans une logomachie (il suffit de regarder ce fil !).
PHP étant un langage vénérable, j'ai pensé que je devrais ajouter à la confusion (même si c'est un résumé des réponses ci-dessus). Parce que, même si deux personnes peuvent avoir raison en même temps, il vaut mieux se casser la tête en une seule réponse.
Tout d'abord, vous devez savoir que vous n'êtes pas un pédant si vous ne répondez pas en noir et blanc . Les choses sont plus compliquées que «oui / non».
Comme vous le verrez, la chose entière par valeur / par référence est très liée à ce que vous faites exactement avec ce tableau dans la portée de votre méthode / fonction: le lire ou le modifier?
Que dit PHP? (alias "en termes de changement")
Le manuel dit ceci (soulignement le mien):
Par défaut, les arguments de fonction sont passés par valeur (de sorte que si la valeur de l'argument dans la fonction est modifiée , elle ne soit pas modifiée en dehors de la fonction). Pour permettre à une fonction de modifier ses arguments, ils doivent être passés par référence .
Pour qu'un argument d'une fonction soit toujours transmis par référence, ajoutez une esperluette (&) au nom de l'argument dans la définition de la fonction
Pour autant que je sache, lorsque de gros programmeurs sérieux et honnêtes envers Dieu parlent de références, ils parlent généralement de modifier la valeur de cette référence . Et c'est exactement ce que les pourparlers manuels sur: hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.
Il y a un autre cas qu'ils ne mentionnent pas: que se passe-t-il si je ne change rien - lisez simplement?
Que se passe-t-il si vous passez un tableau à une méthode qui ne marque pas explicitement une référence et que nous ne changeons pas ce tableau dans la portée de la fonction? Par exemple:
<?php
function readAndDoStuffWithAnArray($array)
{
return $array[0] + $array[1] + $array[2];
}
$x = array(1, 2, 3);
echo readAndDoStuffWithAnArray($x);
Continuez à lire, mon compagnon de voyage.
Que fait réellement PHP? (aka "mémoire-sage")
Les mêmes programmeurs gros et sérieux, quand ils deviennent encore plus sérieux, ils parlent d '"optimisations de mémoire" en ce qui concerne les références. PHP aussi. Parce PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
que c'est pour ça .
Il ne serait pas idéal de passer des tableaux HUGE à diverses fonctions, et PHP pour en faire des copies (c'est ce que fait "pass-by-value", après tout):
<?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);
Eh bien maintenant, si c'était réellement une valeur de passage, nous aurions perdu 3 Mo de RAM, car il y a deux copies de ce tableau, non?
Faux. Tant que nous ne changeons pas la $arr
variable, c'est une référence, en termes de mémoire . Vous ne le voyez tout simplement pas. C'est pourquoi PHP mentionne les références utilisateur-terre lors de la discussion &$someVar
, pour distinguer les références internes et explicites (avec esperluette).
Les faits
Alors, when an array is passed as an argument to a method or function is it passed by reference?
J'ai trouvé trois (ouais, trois) cas:
a) la méthode / fonction lit uniquement l'argument tableau
b) la méthode / fonction modifie l'argument tableau
c) l' argument méthode / fonction tableau est explicitement marqué comme référence (avec un esperluette)
Tout d'abord, voyons combien de mémoire ce tableau consomme réellement (exécutez ici ):
<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840
Que de nombreux octets. Génial.
a) la méthode / fonction lit uniquement l'argument tableau
Faisons maintenant une fonction qui ne lit que ledit tableau comme argument et nous verrons combien de mémoire la logique de lecture prend:
<?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);
Tu veux deviner? J'en ai 80! Voyez par vous-même . C'est la partie que le manuel PHP omet. Si le $arr
paramètre était réellement passé par valeur, vous verriez quelque chose de similaire aux 1331840
octets. Il semble que cela $arr
se comporte comme une référence, n'est-ce pas? C'est parce qu'il est une référence - un interne.
b) la méthode / fonction modifie l'argument tableau
Maintenant, écrivons à ce paramètre, au lieu de le lire:
<?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);
Encore une fois, voyez par vous - même , mais, pour moi, c'est assez proche de 1331840. Donc, dans ce cas, le tableau est en fait copié $arr
.
c) l'argument tableau méthode / fonction est explicitement marqué comme référence (avec une esperluette)
Voyons maintenant combien de mémoire prend une opération d'écriture sur une référence explicite (exécutez ici ) - notez l'esperluette dans la signature de la fonction:
<?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);
Je parie que vous obtenez 200 max! Cela consomme donc autant de mémoire que la lecture d'un paramètre non-esperluette .